Wenn Sie ein großes Objekt in Cloud Storage sequenziell über eine einzelne Verbindung herunterladen, wird die verfügbare Netzwerkbandbreite möglicherweise nicht vollständig genutzt. Wenn Sie ein Objekt in Bytebereichssegmente (sogenannte Stripes) aufteilen und diese Segmente gleichzeitig lesen, können Sie den Downloaddurchsatz für große Objekte mit den Cloud-Clientbibliotheken für Rust verbessern.
In diesem Dokument wird beschrieben, wie Sie große Testobjekte mithilfe der Objektzusammensetzung erstellen, Bytebereiche gleichzeitig mit ReadRange::segment herunterladen und Stripes mit festen Offsets in eine lokale Datei schreiben. Wenn Sie die Clientbibliothek noch nicht kennen, lesen Sie zuerst Cloud Storage mit Rust verwenden.
Hinweis
Bevor Sie den Code in diesem Dokument ausführen, müssen die folgenden Voraussetzungen erfüllt sein:
- Erstellen oder wählen Sie ein Google Cloud -Projekt mit aktivierter Abrechnung aus.
- Erstellen Sie einen dedizierten Cloud Storage-Bucket für Tests in Ihrem Projekt.
- Konfigurieren Sie Standardanmeldedaten für Anwendungen für Ihre Umgebung.
- Weisen Sie Ihrem Hauptkonto eine IAM-Rolle (Identity and Access Management) mit der Berechtigung zum Lesen, Schreiben, Erstellen und Löschen von Objekten im Bucket zu, z. B. Storage-Administrator (
roles/storage.admin).
Abhängigkeiten
Fügen Sie die Cloud Storage-Clientbibliothek und die unterstützenden Crates der Datei Cargo.toml hinzu:
cargo add google-cloud-storage google-cloud-gax anyhow bytes futures
cargo add tokio --features macros,rt-multi-thread
Große Testobjekte erstellen
Wenn Sie gestreifte Downloads testen möchten, ohne Gigabyte an Daten über das Netzwerk hochzuladen, laden Sie ein kleines Seed-Objekt hoch und verwenden Sie den Compose-Vorgang von Cloud Storage, um Kopien serverseitig zu verketten. Führen Sie in einer asynchronen seed-Funktion, die client, control und bucket_name im Format projects/_/buckets/BUCKET_ID akzeptiert, die folgenden Schritte aus:
Importieren Sie
SourceObject, um in Compose-Anfragen auf vorhandene Objekte zu verweisen:Laden Sie ein 1 MiB großes Seed-Objekt mit dem Namen
1MiB.txthoch:Wenn Sie ein 32-MiB-Objekt mit dem Namen
32MiB.txterstellen möchten, verketten Sie 32 Kopien von1MiB.txtauf dem Server:Wenn Sie ein 1-GiB-Objekt mit dem Namen
1GiB.txterstellen möchten, verketten Sie 32 Kopien von32MiB.txt:Wenn Sie Testobjekte mit Zweierpotenzen aus
1GiB.txt(2GiB.txt,4GiB.txt,8GiB.txt,16GiB.txtund32GiB.txt) erstellen möchten, wiederholen Sie den Erstellungsvorgang:
Gleichzeitige Stripe-Downloads koordinieren
Wenn Sie ein Objekt parallel herunterladen möchten, fragen Sie die Größe und Generierung ab, weisen Sie die lokale Zieldatei vorab zu und erstellen Sie ein Future pro Stripe. Führen Sie in einer download-Funktion, die client, control, bucket_name, object_name, stripe_size und destination akzeptiert, die folgenden Schritte aus:
Rufen Sie die Objektmetadaten mit
StorageControl::get_objectab, um die Gesamtgröße des Objekts zu prüfen und nachfolgende Lesevorgänge auf eine einzelne Generierung zu beschränken:Erstellen Sie die Zieldatei und weisen Sie ihr die genaue Objektgröße zu, damit Worker-Aufgaben an unabhängigen Byte-Offsets schreiben können:
Berechnen Sie jeden Stripe-Offset mit
stripe_sizealslimitund erstellen Sie einwrite_stripe-Future pro Segment. Hängen Sie einen letzten Teil-Stripe an, wenn die Objektgröße nicht gleichmäßig durchlimitteilbar ist:Führen Sie alle Stripe-Futures gleichzeitig mit
futures::future::join_allaus und geben Sie alle Fehler weiter:
Einzelnen Stripe herunterladen und schreiben
Jede write_stripe-Aufgabe liest einen einzelnen Bytebereich aus Cloud Storage und schreibt die empfangenen Blöcke mit dem entsprechenden Offset in das freigegebene lokale Dateihandle. So implementierst du write_stripe:
Importieren Sie
ReadRangeund definieren Sie die Funktionwrite_stripe:Erstellen Sie mit
Storage::read_objecteinenReadObject-Anfrage-Builder und senden Sie die Anfrage, nachdem Sie die Optionen für die Generierung und den Lesebereich in den folgenden Schritten konfiguriert haben:Wenn Sie alle Stripes an dieselbe Objektgeneration anpinnen und inkonsistente Lesevorgänge verhindern möchten, falls ein anderer Prozess das Objekt überschreibt, rufen Sie
set_generationim Request Builder auf, bevor Siesendaufrufen:Wenn Sie den Lesevorgang auf den Bytebereich des Stripes beschränken möchten, rufen Sie
set_read_rangemitReadRange::segment(offset, limit)im Request Builder auf:Streamen Sie Chunks vom Reader und schreiben Sie jeden Chunk in die Zieldatei unter
current_posintokio::task::spawn_blocking. Da die Standardbibliothek von Rust keine plattformübergreifende Methode für positionales Schreiben hat, wird in diesem BeispielFileExt::write_all_atunter Unix undFileExt::seek_writeunter Windows verwendet:
Hinweise zur Leistung
Der effektive Durchsatz von Striping-Downloads wird von mehreren Faktoren bestimmt:
- Geschwindigkeit des lokalen Laufwerks. Das Schreiben von Blöcken in einen langsamen lokalen Speicher kann zum Engpass werden. Durch die Verwendung von lokalem SSD-Speicher mit hohem Durchsatz wird sichergestellt, dass die Laufwerks-E/A-Leistung die Netzwerkleistung beim Lesen übersteigt.
- VM-CPU-Kapazität. Cloud Storage verschlüsselt Objektdaten während der Übertragung, sodass der Client jeden empfangenen Block entschlüsselt. Ihre VM muss genügend vCPUs haben, um gleichzeitige TLS-Entschlüsselungen über Stripes hinweg zu verarbeiten.
- Bucket- und VM-Standort. Das Herunterladen über Regionen hinweg führt zu WAN-Latenz und schränkt den Durchsatz ein. Platzieren Sie Ihre VM nach Möglichkeit in derselben Region wie Ihren Bucket.
Sie können auch mit der Abstimmung von stripe_size experimentieren, um zu vermeiden, dass ein sehr kleiner Reststreifen übrig bleibt oder zu viele kleine Bereichsanfragen erstellt werden.
Vollständiger Code
Im folgenden Beispiel werden die Funktionen seed, download und write_stripe zu einem vollständigen Modul kombiniert:
Wenn Sie download für ein 32-MiB-Objekt mit einem 1-MiB-stripe_size ausführen, sieht die Ausgabe in etwa so aus und enthält die heruntergeladene Größe, die verstrichene Zeit, die Anzahl der Stripes und die effektive Bandbreite:
Completed 32.00 MiB download in 412.5ms, using 32 stripes, effective bandwidth = 77.58 MiB/s
Bereinigen
Damit Ihrem Google Cloud -Konto die von seed erstellten Testobjekte nicht in Rechnung gestellt werden, löschen Sie die Testobjekte und löschen Sie Ihren Test-Bucket, wenn Sie fertig sind. Entfernen Sie auch die lokale Zieldatei.