Leistungsoptimierung für Uploads und Downloads mit .NET
Wenn eine Anwendung Daten unter Verwendung der Azure Storage-Clientbibliothek für .NET überträgt, gibt es mehrere Faktoren, die sich auf die Geschwindigkeit, die Arbeitsspeicherauslastung und sogar auf den Erfolg 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 zur Optimierung von Datenübertragungsoptionen erläutert. Der Leitfaden gilt für alle APIs, die StorageTransferOptions
als Parameter akzeptieren. Bei ordnungsgemäßer Optimierung kann die Clientbibliothek Daten effizient auf mehrere Anforderungen verteilen, um die Betriebsgeschwindigkeit, Arbeitsspeicherauslastung und Netzwerkstabilität zu verbessern.
Leistungsoptimierung mit StorageTransferOptions
Die ordnungsgemäße Optimierung der Werte in StorageTransferOptions ist der Schlüssel zu zuverlässiger Leistung bei Datenübertragungsvorgängen. Speicherübertragungen werden basierend auf den Eigenschaftswerten, die in einer Instanz dieser Struktur definiert sind, 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.
Die folgenden Eigenschaften von StorageTransferOptions
können basierend auf den Anforderungen Ihrer App optimiert werden:
- InitialTransferSize: Die Größe der ersten Anforderung in Bytes
- MaximumConcurrency: Die maximale Anzahl von Teilübertragungen, die parallel verwendet werden können
- MaximumTransferSize: Die maximale Länge einer Übertragung in Bytes
Hinweis
Die Struktur StorageTransferOptions
lässt zwar Nullwerte zu, die Clientbibliotheken verwenden jedoch Standardwerte für die einzelnen Werte, wenn kein Wert angegeben wird. 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. Eine mangelhafte Optimierung von StorageTransferOptions
kann zu übermäßig langen Vorgängen und sogar zu Anforderungstimeouts führen. Es empfiehlt sich, die Werte in StorageTransferOptions
proaktiv zu testen und sie basierend auf den Anforderungen Ihrer Anwendung und Umgebung zu optimieren.
InitialTransferSize
InitialTransferSize ist die Größe der ersten Bereichsanforderung in Bytes. Eine HTTP-Bereichsanforderung ist eine partielle Anforderung, deren Größe in diesem Fall durch InitialTransferSize
definiert ist. Blobs mit einer geringeren Größe werden in einer einzelnen Anforderung übertragen. Größere Blobs werden weiterhin in Blöcken mit der Größe MaximumTransferSize
übertragen.
Wichtig: Der für InitialTransferSize
definierte Wert wird nicht durch den für MaximumTransferSize
angegebenen Wert eingeschränkt. InitialTransferSize
definiert eine separate Größenbeschränkung für eine erste Anforderung, um den gesamten Vorgang auf einmal und ohne Teilübertragungen auszuführen. InitialTransferSize
sollte häufig mindestens so groß sein wie der für MaximumTransferSize
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, InitialTransferSize
auf den für MaximumTransferSize
verwendeten Wert festzulegen.
Hinweis
Bei Verwendung eines BlobClient
-Objekts werden Blobs, die kleiner sind als InitialTransferSize
, nicht mithilfe von Put Block, sondern mithilfe von Put Blob hochgeladen.
MaximumConcurrency
MaximumConcurrency ist die maximale Anzahl von Workern, die in einer parallelen Übertragung verwendet werden können. Derzeit können Übertragungen nur in asynchronen Vorgängen parallelisiert werden. Bei synchronen Vorgängen wird dieser Wert ignoriert und eine sequenzielle Ausführung verwendet.
Die Effektivität dieses Werts hängt von den Grenzwerten für Verbindungspools in .NET ab, die in bestimmten Szenarien standardmäßig die Leistung einschränken. Weitere Informationen zu den Grenzwerten für Verbindungspools in .NET finden Sie unter Grenzwerte für Verbindungspools in .NET Framework und das neue Azure SDK für .NET.
MaximumTransferSize
MaximumTransferSize ist die maximale Länge einer Übertragung in Bytes. InitialTransferSize
wird wie bereits erwähnt nicht durch diesen Wert eingeschränkt und kann größer sein als MaximumTransferSize
.
Zur Gewährleistung eines effizienten Datenflusses erreichen die Clientbibliotheken möglicherweise nicht bei jeder Übertragung den Wert von MaximumTransferSize
. Je nach Vorgang kann der unterstützte Maximalwert für die Übertragungsgröße variieren. Bei Blockblobs, die den Vorgang Put Block mit der Dienstversion 2019-12-12 oder mit einer höheren Version aufrufen, beträgt die maximale Blockgröße beispielsweise 4.000 MiB. 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
Die Clientbibliothek enthält Überladungen für die Methoden Upload
und UploadAsync
, die eine StorageTransferOptions-Instanz als Teil eines BlobUploadOptions-Parameters akzeptieren. Ähnliche Überladungen sind auch für die Methoden DownloadTo
und DownloadToAsync
verfügbar. Hier wird ein BlobDownloadToOptions-Parameter verwendet.
Das folgende Codebeispiel zeigt, wie Sie Werte für eine StorageTransferOptions
-Instanz definieren und diese Konfigurationsoptionen als Parameter an UploadAsync
übergeben. 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.
// Specify the StorageTransferOptions
BlobUploadOptions options = new BlobUploadOptions
{
TransferOptions = new StorageTransferOptions
{
// Set the maximum number of parallel transfer workers
MaximumConcurrency = 2,
// Set the initial transfer length to 8 MiB
InitialTransferSize = 8 * 1024 * 1024,
// Set the maximum length of a transfer to 4 MiB
MaximumTransferSize = 4 * 1024 * 1024
}
};
// Upload data from a stream
await blobClient.UploadAsync(stream, options);
In diesem Beispiel wird die Anzahl von Workern für die parallele Übertragung mithilfe der Eigenschaft MaximumConcurrency
auf „2“ festgelegt. Bei dieser Konfiguration werden bis zu zwei Verbindungen gleichzeitig geöffnet, um einen parallelen Uploadvorgang zu ermöglichen. Von der anfänglichen HTTP-Bereichsanforderung wird versucht, bis zu 8 MiB an Daten hochzuladen, wie durch die Eigenschaft InitialTransferSize
definiert. Beachten Sie, dass InitialTransferSize
nur bei Verwendung eines suchbaren Datenstroms für Uploads gilt. Wenn das Blob kleiner als 8 MiB ist, ist für den Vorgang nur eine einzelne Anforderung erforderlich. Ist das Blob größer als 8 MiB, haben alle nachfolgenden Übertragungsanforderungen eine maximale Größe von 4 MiB, wie durch die Eigenschaft MaximumTransferSize
festgelegt.
Überlegungen zur Leistung bei Uploads
Während eines Uploads teilen die Storage-Clientbibliotheken einen Uploaddatenstrom basierend auf den in der StorageTransferOptions
-Instanz definierten Werten in mehrere Teiluploads auf. Jeder Teilupload verfügt über einen eigenen dedizierten Aufruf des REST-Vorgangs. Bei einem Objekt vom Typ BlobClient
oder BlockBlobClient
wird der Vorgang Put Block verwendet. Bei einem DataLakeFileClient
-Objekt wird der Vorgang Append Data verwendet. Die Storage-Clientbibliothek verwaltet diese REST-Vorgänge parallel (abhängig von den Übertragungsoptionen), um den gesamten Upload abzuschließen.
Die Behandlung von Pufferung und InitialTransferSize
durch die Clientbibliothek ist abhängig vom Suchbarkeitsstatus des Uploaddatenstroms, wie in den folgenden Abschnitten beschrieben. Ein suchbarer Datenstrom ist ein Datenstrom, der das Abfragen und Ändern der aktuellen Position in einem Datenstrom unterstützt. Weitere Informationen zu Datenströmen in .NET finden Sie in der Referenz zur Stream-Klasse.
Hinweis
Blockblobs haben eine maximale Blockanzahl von 50.000 Blöcken. Die maximale Größe Ihres Blockblobs entspricht also 50.000 mal MaximumTransferSize
.
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 Resilienz für nicht suchbare Datenstromuploads zu gewährleisten, puffern die Storage-Clientbibliotheken Daten für jeden einzelnen REST-Aufruf vor dem Start des Uploads. Neben den Einschränkungen durch die Netzwerkgeschwindigkeit ist dieses Pufferverhalten ein Grund dafür, einen kleineren Wert für MaximumTransferSize
in Betracht zu ziehen, auch wenn Uploadvorgänge nacheinander ausgeführt werden. Durch Verringern des Werts von MaximumTransferSize
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 MaximumTransferSize
die Pufferzeit, was wiederum die Leistung verbessern kann.
Ein weiteres Szenario mit Pufferung ist das Hochladen von Daten mit parallelen REST-Aufrufen zur Maximierung des Netzwerkdurchsatzes. Die Clientbibliotheken benötigen Quellen, aus denen sie parallel lesen können. Da Datenströme sequenziell sind, werden die Daten für jeden einzelnen REST-Aufruf vor dem Start des Uploads gepuffert. Dieses Pufferverhalten tritt auch auf, wenn der bereitgestellte Datenstrom suchbar ist.
Um das Puffern während eines asynchronen Uploadaufrufs zu vermeiden, müssen Sie einen suchbaren Datenstrom bereitstellen und MaximumConcurrency
auf „1“ festlegen. Diese Strategie sollte in den meisten Situationen funktionieren. Sollte Ihr Code allerdings andere Clientbibliotheksfeatures verwenden, die eine Pufferung erfordern, kann es sein, dass trotzdem Daten gepuffert werden.
InitialTransferSize beim Hochladen
Wenn für den Upload ein suchbarer Datenstrom bereitgestellt wird, wird die Datenstromlänge anhand des Werts von InitialTransferSize
überprüft. Ist die Datenstromlänge geringer als dieser Wert, wird der gesamte Datenstrom unabhängig von anderen StorageTransferOptions
-Werten als einzelner REST-Aufruf hochgeladen. Andernfalls wird der Upload wie zuvor beschrieben aufgeteilt. Bei einem nicht suchbaren Datenstrom hat InitialTransferSize
keine Auswirkung und wird ignoriert.
Überlegungen zur Leistung bei Downloads
Während eines Downloads teilen die Storage-Clientbibliotheken eine Downloadanforderung basierend auf den in der StorageTransferOptions
-Instanz definierten Werten in mehrere Teildownloads auf. 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.
Puffern bei Downloads
Das gleichzeitige Empfangen mehrerer HTTP-Antworten mit Textinhalten hat Auswirkungen auf die Speicherauslastung. Von den Storage-Clientbibliotheken wird jedoch nicht explizit ein Pufferschritt für heruntergeladene Inhalte hinzugefügt. Eingehende Antworten werden der Reihe nach verarbeitet. Die Clientbibliotheken konfigurieren einen 16-KB-Puffer für das Kopieren von Datenströmen aus einem HTTP-Antwortdatenstrom in einen vom Aufrufer bereitgestellten Zieldatenstrom oder Dateipfad.
InitialTransferSize beim Herunterladen
Während eines Downloads übermitteln die Storage-Clientbibliotheken zunächst eine einzelne Downloadbereichsanforderung mithilfe von InitialTransferSize
. 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 MaximumTransferSize
), bis der gesamte Download abgeschlossen ist.
Nächste Schritte
- Dieser Artikel ist Teil des Blob Storage-Entwicklerleitfadens für .NET. Die vollständige Liste der Artikel im Entwicklerleitfaden finden Sie unter Erstellen Ihrer App.
- Weitere Informationen zu Faktoren, die die Leistung von Azure Storage-Vorgängen beeinflussen können, finden Sie unter Latenz im Blobspeicher.
- Eine Liste der Entwurfsüberlegungen zum Optimieren der Leistung für Apps mit Blob Storage finden Sie in der Checkliste zu Leistung und Skalierbarkeit für Blob Storage.