Leistungsoptimierung für Uploads und Downloads mit Python

Wenn eine Anwendung Daten mithilfe der Azure Storage-Clientbibliothek für Python überträgt, gibt es mehrere Faktoren, die sich auf die Geschwindigkeit, die Arbeitsspeicherauslastung und sogar auf den Erfolg oder das Fehlschlagen der Anforderung auswirken können. Um die Leistung und Zuverlässigkeit bei Datenübertragungen zu maximieren, ist es wichtig, proaktiv die Übertragungsoptionen für Clientbibliotheken basierend auf der Umgebung zu konfigurieren, in der Ihre App ausgeführt wird.

In diesem Artikel werden mehrere Überlegungen zum Optimieren von Datenübertragungsoptionen erläutert. Bei ordnungsgemäßer Optimierung kann die Clientbibliothek Daten effizient auf mehrere Anforderungen verteilen, um die Betriebsgeschwindigkeit, Arbeitsspeicherauslastung und Netzwerkstabilität zu verbessern.

Leistungsoptimierung für Uploads

Die richtige Optimierung von Datenübertragungsoptionen ist der Schlüssel für eine zuverlässige Leistung bei Uploads. Speicherübertragungen werden basierend auf den Werten dieser Argumente in mehrere Teilübertragungen unterteilt. Die maximale unterstützte Übertragungsgröße variiert je nach Vorgang und Dienstversion. Überprüfen Sie daher unbedingt die Dokumentation, um die Grenzwerte zu ermitteln. Weitere Informationen zu Grenzwerten im Zusammenhang mit Übertragungsgröße für Blob Storage finden Sie unter Skalierbarkeitsziele für Blob Storage.

Festlegen von Übertragungsoptionen für Uploads

Die folgenden Argumente können basierend auf den Anforderungen Ihrer App optimiert werden:

  • max_single_put_size: Die maximale Größe für ein Blob, das mit einer einzelnen Anforderung hochgeladen werden soll. Der Standardwert ist 64 MiB.
  • max_block_size: Die maximale Länge einer Übertragung in Bytes beim Hochladen eines Blockblobs in Blöcken. Der Standardwert ist 4 MiB.
  • max_concurrency: Die maximale Anzahl von Teilübertragungen, die parallel verwendet werden können.

Hinweis

Sofern nicht angegeben, verwenden die Clientbibliotheken für jede Datenübertragungsoption Standardwerte. Mit diesen Standardwerten lässt sich zwar in der Regel in einer Rechenzentrumsumgebung eine hohe Leistung erzielen, für Umgebungen von Privatanwendern sind sie jedoch eher nicht geeignet. Unzureichend optimierte Datenübertragungsoptionen können zu übermäßig langen Vorgängen und sogar zu Anforderungstimeouts führen. Es empfiehlt sich, diese Werte proaktiv zu testen und dann basierend auf den Anforderungen Ihrer Anwendung und Umgebung zu optimieren.

„max_single_put_size“

Das Argument max_single_put_size ist die maximale Blobgröße in Bytes für einen einzelnen Anforderungsupload. Wenn die Blobgröße kleiner oder gleich max_single_put_size ist, wird das Blob mit einer einzelnen Put Blob-Anforderung hochgeladen. Wenn die Blobgröße größer als max_single_put_sizeoder aber unbekannt ist, wird das Blob mithilfe einer Reihe von Put Block-Aufrufen, gefolgt von Put Block List, in Blöcken hochgeladen.

Wichtig: Der für max_single_put_size definierte Wert wird nicht durch den für max_block_size angegebenen Wert eingeschränkt. Das Argument max_single_put_size definiert eine separate Größenbeschränkung für eine Anforderung, um den gesamten Vorgang auf einmal (ohne Teilübertragungen) durchzuführen. max_single_put_size sollte häufig mindestens so groß sein wie der für max_block_size definierte Wert. Abhängig von der Größe der Datenübertragung kann dieser Ansatz leistungsfähiger sein, da die Übertragung im Rahmen einer einzelnen Anforderung erfolgt und den mit mehreren Anforderungen verbundenen Mehraufwand vermeidet.

Sollten Sie unsicher sein, welcher Wert für Ihre Situation am besten geeignet ist, empfiehlt es sich, max_single_put_size auf den für max_block_size verwendeten Wert festzulegen.

„max_block_size“

Das Argument max_block_size ist die maximale Länge einer Übertragung in Bytes beim Hochladen eines Blockblobs in Blöcken. max_single_put_size wird wie bereits erwähnt nicht durch diesen Wert eingeschränkt und kann größer sein als max_block_size.

Zur Gewährleistung eines effizienten Datenflusses erreichen die Clientbibliotheken möglicherweise nicht bei jeder Übertragung den Wert von max_block_size. Je nach Vorgang kann der unterstützte Maximalwert für die Übertragungsgröße variieren. Weitere Informationen zu Grenzwerten im Zusammenhang mit der Übertragungsgröße für Blob Storage finden Sie im Diagramm unter Skalierbarkeitsziele für Blob Storage.

Codebeispiel

Das folgende Codebeispiel zeigt, wie beim Erstellen eines BlobClient-Objekts Datenübertragungsoptionen angegeben und Daten mithilfe dieses Clientobjekts hochgeladen werden. Die in diesem Beispiel angegebenen Werte sind nicht als Empfehlungen zu verstehen. Zur ordnungsgemäßen Optimierung dieser Werte müssen die spezifischen Anforderungen Ihrer App berücksichtigt werden.

def upload_blob_transfer_options(self, account_url: str, container_name: str, blob_name: str):
    # Create a BlobClient object with data transfer options for upload
    blob_client = BlobClient(
        account_url=account_url, 
        container_name=container_name, 
        blob_name=blob_name,
        credential=DefaultAzureCredential(),
        max_block_size=1024*1024*4, # 4 MiB
        max_single_put_size=1024*1024*8 # 8 MiB
    )
    
    with open(file=os.path.join(r'file_path', blob_name), mode="rb") as data:
        blob_client = blob_client.upload_blob(data=data, overwrite=True, max_concurrency=2)

In diesem Beispiel wird die Anzahl von Workern für die parallele Übertragung mithilfe des Arguments max_concurrency für den Methodenaufruf auf „2“ festgelegt. Bei dieser Konfiguration werden bis zu zwei Verbindungen gleichzeitig geöffnet, um einen parallelen Uploadvorgang zu ermöglichen. Während der Clientinstanziierung wird das Argument max_single_put_size auf 8 MiB festgelegt. Wenn das Blob kleiner als 8 MiB ist, ist zum Abschließen des Uploadvorgangs nur eine einzelne Anforderung erforderlich. Wenn die Blobgröße größer als 8 MiB ist, wird das Blob in Blöcken mit einer maximalen Blockgröße von 4 MiB hochgeladen, wie durch das Argument max_block_size festgelegt wurde.

Überlegungen zur Leistung bei Uploads

Während eines Uploads teilen die Storage-Clientbibliotheken einen bestimmten Uploaddatenstrom in mehrere Teiluploads auf, die auf den während der Clientkonstruktion definierten Konfigurationsoptionen basieren. Jeder Teilupload verfügt über einen eigenen dedizierten Aufruf des REST-Vorgangs. Bei einem BlobClient-Objekt wird der Vorgang Put Block verwendet. Die Storage-Clientbibliothek verwaltet diese REST-Vorgänge parallel (abhängig von den Übertragungsoptionen), um den gesamten Upload abzuschließen.

In den folgenden Abschnitten erfahren Sie, wie die Clientbibliothek die Pufferung durchführt.

Hinweis

Blockblobs haben eine maximale Blockanzahl von 50.000 Blöcken. Die maximale Größe Ihres Blockblobs entspricht also 50.000 mal max_block_size.

Puffern bei Uploads

Das Fortsetzen angehaltener REST-Uploadvorgänge wird von der Storage-REST-Ebene nicht unterstützt. Einzelne Übertragungen werden entweder abgeschlossen oder gehen verloren. Um bei Datenstromuploads Resilienz sicherzustellen, puffern die Storage-Clientbibliotheken Daten für jeden einzelnen REST-Aufruf, bevor der Upload gestartet wird. Neben den Einschränkungen durch die Netzwerkgeschwindigkeit ist dieses Pufferverhalten ein Grund dafür, einen kleineren Wert für max_block_size in Betracht zu ziehen, auch wenn Uploadvorgänge nacheinander ausgeführt werden. Durch Verringern des Werts von max_block_size verringert sich die maximale Datenmenge, die für die einzelnen Anforderungen bzw. für Wiederholungsversuche bei fehlerhaften Anforderungen gepuffert wird. Falls bei Datenübertragungen mit einer bestimmten Größe häufig Timeouts auftreten, verringert die Senkung des Werts von max_block_size die Pufferzeit, was wiederum die Leistung verbessern kann.

Standardmäßig puffert das SDK Daten von max_block_size Bytes pro gleichzeitiger Teiluploadanforderung, doch die Arbeitsspeichernutzung kann auf 4 MiB pro Anforderung begrenzt werden, wenn die folgenden Bedingungen erfüllt sind:

  • Das Argument max_block_size muss größer als min_large_block_upload_threshold sein. Das Argument min_large_block_upload_threshold kann während der Clientinstanziierung definiert werden und ist die minimale Blockgröße in Bytes, die für die Verwendung des speichereffizienten Algorithmus erforderlich ist. Der Standardwert für das Argument min_large_block_upload_threshold ist 4*1024*1024 + 1.
  • Der bereitgestellte Datenstrom muss durchsuchbar sein. Ein suchbarer Datenstrom ist ein Datenstrom, der das Abfragen und Ändern der aktuellen Position in einem Datenstrom unterstützt.
  • Das Blob muss ein Blockblob sein.

Diese Strategie trifft in den meisten Situationen zu. Wenn Ihr Code aber andere Clientbibliotheksfeatures verwendet, die eine Pufferung erfordern, kann es sein, dass Daten weiterhin gepuffert werden.

Leistungsoptimierung für Downloads

Die richtige Optimierung von Datenübertragungsoptionen ist der Schlüssel für eine zuverlässige Leistung bei Downloads. Speicherübertragungen werden basierend auf den Werten dieser Argumente in mehrere Teilübertragungen unterteilt.

Festlegen von Übertragungsoptionen für Downloads

Die folgenden Argumente können basierend auf den Anforderungen Ihrer App optimiert werden:

  • max_chunk_get_size: Die maximale Blockgröße, die zum Herunterladen eines Blobs verwendet wird. Der Standardwert ist 4 MiB.
  • max_concurrency: Die maximale Anzahl von Teilübertragungen, die parallel verwendet werden können.
  • max_single_get_size: Die maximale Größe für ein Blob, das in einem einzigen Aufruf heruntergeladen werden soll. Wenn die Gesamtblobgröße max_single_get_size überschreitet, wird der Rest der Blobdaten in Blöcken heruntergeladen. Der Standardwert ist 32 MiB.

Codebeispiel

def download_blob_transfer_options(self, account_url: str, container_name: str, blob_name: str):
    # Create a BlobClient object with data transfer options for download
    blob_client = BlobClient(
        account_url=account_url, 
        container_name=container_name, 
        blob_name=blob_name,
        credential=DefaultAzureCredential(),
        max_single_get_size=1024*1024*32, # 32 MiB
        max_chunk_get_size=1024*1024*4 # 4 MiB
    )

    with open(file=os.path.join(r'file_path', 'file_name'), mode="wb") as sample_blob:
        download_stream = blob_client.download_blob(max_concurrency=2)
        sample_blob.write(download_stream.readall())

Überlegungen zur Leistung bei Downloads

Während eines Downloads teilen die Storage-Clientbibliotheken eine bestimmte Downloadanforderung in mehrere Teildownloads auf, die auf den während der Clientkonstruktion definierten Konfigurationsoptionen basieren. Jeder Teildownload verfügt über einen eigenen dedizierten Aufruf des REST-Vorgangs. Abhängig von den Übertragungsoptionen verwalten die Clientbibliotheken die REST-Vorgänge parallel, um den gesamten Download abzuschließen.

„max_single_get_size“ für Downloads

Während eines Downloads übermitteln die Storage-Clientbibliotheken zunächst eine einzelne Downloadbereichsanforderung mithilfe von max_single_get_size. Während dieser ersten Downloadanforderung ist den Clientbibliotheken die Gesamtgröße der Ressource bekannt. Wenn der gesamte Inhalt im Rahmen der anfänglichen Anforderung erfolgreich heruntergeladen wurde, ist der Vorgang abgeschlossen. Andernfalls übermitteln die Clientbibliotheken weiterhin Bereichsanforderungen (bis maximal max_chunk_get_size), bis der gesamte Download abgeschlossen ist.

Nächste Schritte