Vorbedingungen für Anfragen

Auf dieser Seite werden Vorbedingungen für Anfragen erläutert, mit denen Sie verhindern können, dass Anfragen auf eine Ressource angewendet werden, wenn sich die Ressource in einem unerwarteten Zustand befindet.

Einführung

Bei Verwendung von Vorbedingungen in einer Anfrage an Cloud Storage wird die Anfrage nur fortgesetzt, wenn die Zielressource die in den Vorbedingungen definierten Kriterien erfüllt. Mit Vorbedingungsprüfungen wird sichergestellt, dass sich ein Bucket oder Objekt im erwarteten Zustand befindet, sodass Sie sichere Read-Modify-Write-Aktualisierungen und bedingte Vorgänge ausführen können.

Vorbedingungen werden häufig verwendet, um Race-Bedingungen bei Änderungsanfragen wie Uploads, Löschungen oder Metadatenaktualisierungen zu verhindern. Race-Bedingungen können auftreten, wenn dieselbe Anfrage mehrmals gesendet wird oder wenn unabhängige Prozesse versuchen, dieselbe Ressource zu ändern. Weitere Informationen finden Sie unter Beispiele für Race-Bedingungen und Datenbeschädigung. Vorbedingungen werden häufig auch beim Abrufen von Objektmetadaten und Daten in aufeinanderfolgenden Anfragen verwendet, um sicherzustellen, dass sich das Objekt zwischen den beiden Anfragen nicht geändert hat.

Vorbedingungskriterien

Cloud Storage unterstützt die Verwendung verschiedener unveränderlicher Ressourcenattribute in Vorbedingungen:

In der folgenden Tabelle sind die von der JSON API und der XML API unterstützten Vorbedingungen aufgeführt:

JSON API XML API Beschreibung
ifGenerationMatch-Abfrageparameter x-goog-if-generation-match-Header Die Anfrage wird fortgesetzt, wenn die generation der Zielressource mit dem in der Vorbedingung verwendeten Wert übereinstimmt. Wenn die Werte nicht übereinstimmen, schlägt die Anfrage mit der Antwort 412 Precondition Failed fehl.
ifMetagenerationMatch-Abfrageparameter x-goog-if-metageneration-match-Header Die Anfrage wird fortgesetzt, wenn die metageneration der Zielressource mit dem in der Vorbedingung verwendeten Wert übereinstimmt. Wenn die Werte nicht übereinstimmen, schlägt die Anfrage mit der Antwort 412 Precondition Failed fehl.
ifGenerationNotMatch-Abfrageparameter Die Anfrage wird fortgesetzt, wenn die generation der Zielressource nicht mit dem in der Vorbedingung verwendeten Wert übereinstimmt. Wenn die Werte übereinstimmen, schlägt die Anfrage mit der Antwort 304 Not Modified fehl.
ifMetagenerationNotMatch-Abfrageparameter Die Anfrage wird fortgesetzt, wenn die metageneration der Zielressource nicht mit dem in der Vorbedingung verwendeten Wert übereinstimmt. Wenn die Werte übereinstimmen, schlägt die Anfrage mit der Antwort 304 Not Modified fehl.
If-Match-Header If-Match-Header Gilt für Anfragen, bei denen Daten abgerufen werden. Die Anfrage wird fortgesetzt, wenn die ETag der Zielressource mit dem in der Vorbedingung verwendeten Wert übereinstimmt. Wenn die Werte nicht übereinstimmen, schlägt die Anfrage mit der Antwort 412 Precondition Failed fehl.
If-None-Match-Header If-None-Match-Header Gilt für Anfragen, bei denen Daten abgerufen werden. Die Anfrage wird fortgesetzt, wenn die ETag der Zielressource nicht mit dem in der Vorbedingung verwendeten Wert übereinstimmt. Wenn die Werte übereinstimmen, schlägt die Anfrage mit der Antwort 304 Not Modified fehl.
If-Modified-Since-Header Die Anfrage wird fortgesetzt, wenn das Last-Modified-Datum der Zielressource nach dem in der Vorbedingung verwendeten Wert liegt. Wenn die Zielressource diese Vorbedingung nicht erfüllt, schlägt die Anfrage mit der Antwort 304 Not Modified fehl.
If-Unmodified-Since-Header Die Anfrage wird fortgesetzt, wenn das Last-Modified-Datum der Zielressource vor dem Wert liegt, der in der Vorbedingung verwendet wird, oder diesem entspricht. Wenn die Zielressource diese Vorbedingung nicht erfüllt, schlägt die Anfrage mit der Antwort 412 Precondition Failed fehl.

Vorbedingungen für die Objektzusammensetzung

Bei der Objektzusammensetzung unterstützen sowohl die JSON API als auch die XML API Folgendes:

  • Die Vorbedingungen „generation-match“ und „metageneration-match“ für das Zielobjekt.

  • Die "generation-match"-Vorbedingung für jedes Quellobjekt. Die Verwendung dieser Vorbedingung verhindert, dass unzulässige Komponenten verwendet werden, wenn ein unabhängiger Prozess eine der beabsichtigten Komponenten der Zusammensetzung überschreibt. Wenn Sie Vorbedingungen verwenden und eine solche Überschreibung erfolgt, schlägt der compose-Vorgang mit der 412 Precondition Failed-Antwort fehl.

Vorbedingungen für das Kopieren von Objekten

Beim Kopieren oder Neuschreiben eines Objekts in Cloud Storage unterstützen sowohl die JSON API als auch die XML API Standard-vorbedingungen für das Zielobjekt. Jede API bietet eine zusätzliche Unterstützung von Vorbedingungen für Quellobjekte:

  • Die JSON API unterstützt die Vorbedingungen "generation" and "metageneration" für das Quellobjekt, die mithilfe von Abfrageparametern angegeben werden, die das Präfix ifSource haben.

  • Alle von der XML API unterstützten Voraussetzungen können für das Quellobjekt verwendet werden. Diese Voraussetzungen werden in Headern mit dem Präfix x-goog-copy-source- angegeben.

Der 0-Wert in einer generation-match-Vorbedingung

Die generation-match-Vorbedingung akzeptiert den Wert 0 als Sonderfall. Wenn eine generation-match-Vorbedingung mit dem Wert 0 in einer Anfrage enthalten ist, wird die Anfrage nur fortgesetzt, wenn kein Objekt mit dem angegebenen Namen im Bucket vorhanden ist oder es nur nicht aktuelle Versionen des Objekts im Bucket gibt. Wenn eine Live-Version mit dem angegebenen Namen vorhanden ist, schlägt die Anfrage mit dem Statuscode 412 Precondition Failed fehl.

Best Practices und Überlegungen

  • Sie können mehrere Vorbedingungen in einer einzelnen Anfrage verwenden. Wenn eine der Vorbedingungen nicht erfüllt ist, schlägt die Gesamtanfrage fehl.

  • Buckets haben keine Generierungsnummer, obwohl sie eine Metagenerierungsnummer haben. Sie sollten in einer Bucket-Anfrage keine Vorbedingungen verwenden, die eine Generierungsnummer angeben.

  • Wenn Sie eine Metagenerations-Vorbedingung für eine Objektanfrage verwenden, sollten Sie immer auch eine Generations-Vorbedingung verwenden. Dadurch wird verhindert, dass die Anfrage bei einem anderen Objekt erfolgreich ist, das zufällig eine Meta-Generierungsnummer hat, die die Vorbedingung erfüllt.

  • Bei Buckets, die sowohl Live- und nicht aktuelle Objektversionen haben, gelten Objektanfragen nicht für nicht aktuelle Versionen, es sei denn, eine Generierungsnummer ist explizit in der Anfrage angegeben. Dies bedeutet, dass eine allgemeine Anfrage, die Vorbedingungen verwendet, fehlschlägt, wenn die Live-Version nicht mit der Vorbedingung übereinstimmt, unabhängig davon, ob eine nicht aktuelle Version mit den Vorbedingungen übereinstimmt.

  • In der Regel sollten Sie die Vorbedingungen generation und metageneration anstelle von ETag-Vorbedingungen verwenden. Mit der kombinierten Verwendung von generation- und metageneration-Nummern haben Sie die Möglichkeit, alle Objektaktualisierungen einschließlich Metadatenänderungen zu erfassen. Dies ist wesentlich zuverlässiger als ETags. Außerdem sind Generierungs- und Meta-Generierungsnummern über alle APIs hinweg konsistent, ETags jedoch nicht.

  • Vorbedingungen können nicht in mehrteiligen XML API-Uploads verwendet werden. Bei einem entsprechenden Versuch wird ein Fehler ausgegeben.400 NotImplemented

Kosten für Vorbedingungen

In vielen Architekturen, die Vorbedingungen verwenden, müssen Sie vor der Hauptanfrage eine Objektmetadatenanfrage stellen, um die aktuelle Generierungsnummer und/oder Metagenerierungsnummer zu ermitteln:

  • Eine zusätzliche Anfrage bedeutet, dass Sie den Netzwerkanteil der Gesamtvorgangslatenz verdoppeln können, wenn Sie einen zusätzlichen Umlauf hinzufügen. Dies kann bei latenzempfindlichen Vorgängen ein wichtiger Faktor sein.

Je nach Anwendung haben Sie jedoch mehrere Möglichkeiten, die Auswirkungen der Verwendung von Vorbedingungen zu reduzieren, wie zum Beispiel:

  • Speichern Sie die Generierungsnummern und Meta-Generierungsnummern Ihrer Objekte lokal, damit Sie die korrekten Nummern zur Verwendung in den Vorbedingungen bereits kennen.
  • Wenn Ihnen klar ist, welche Objekte neu erstellt werden, wissen Sie auch im Voraus, wann die Vorbedingung if-generation-match:0 verwendet werden muss.

Beispiel: Vorbedingung verwenden

Im folgenden Beispiel wird die generation-match-Vorbedingung in einer Anfrage zum Hochladen eines Objekts verwendet. Damit die Anfrage fortgesetzt werden kann, muss im Bucket ein bereits vorhandenes Objekt mit dem angegebenen Namen gespeichert sein. Die Generierungsnummer für das vorhandene Objekt muss mit der Nummer in der Vorbedingung übereinstimmen:

Befehlszeile

Verwenden Sie das --if-generation-match-Flag zusammen mit dem normalen Befehl:

gcloud storage cp OBJECT_LOCATION gs://DESTINATION_BUCKET_NAME --if-generation-match=GENERATION

Dabei gilt:

  • GENERATION ist die beabsichtigte Generierungsnummer des Objekts, das Sie ersetzen. Beispiel: 1122334455667788.

  • OBJECT_LOCATION ist der lokale Pfad zu Ihrem Objekt. Beispiel: Desktop/dog.png.

  • DESTINATION_BUCKET_NAME ist der Name des Buckets, in den Sie das Objekt hochladen. Beispiel: my-bucket.

JSON API

  1. Die gcloud CLI installieren und initialisieren, um ein Zugriffstoken für den Header Authorization zu generieren.

  2. Verwenden Sie cURL, um die JSON API mit einer POST-Objekt-Anfrage aufzurufen:

    curl -X POST --data-binary @OBJECT_LOCATION \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: OBJECT_CONTENT_TYPE" \
      "https://storage.googleapis.com/upload/storage/v1/b/BUCKET_NAME/o?uploadType=media&name=OBJECT_NAME"&ifGenerationMatch=GENERATION"

    Dabei gilt:

    • OBJECT_LOCATION ist der lokale Pfad zu Ihrem Objekt. Beispiel: Desktop/dog.png.
    • OBJECT_CONTENT_TYPE ist der Inhaltstyp des Objekts. Beispiel: image/png.
    • BUCKET_NAME ist der Name des Buckets, in den Sie das Objekt hochladen. Beispiel: my-bucket.
    • OBJECT_NAME ist der Name, den Sie dem Objekt geben möchten. Beispiel: dog.png.
    • GENERATION ist die beabsichtigte Generierungsnummer des Objekts, das Sie ersetzen. Beispiel: 1122334455667788.

XML API

  1. Die gcloud CLI installieren und initialisieren, um ein Zugriffstoken für den Header Authorization zu generieren.

  2. Verwenden Sie cURL, um die XML API mit einer PUT-Objektanfrage aufzurufen:

    curl -X PUT --data-binary @OBJECT_LOCATION \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: OBJECT_CONTENT_TYPE" \
      -H "x-goog-if-generation-match: GENERATION" \
      "https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME"

    Dabei gilt:

    • OBJECT_LOCATION ist der lokale Pfad zu Ihrem Objekt. Beispiel: Desktop/dog.png.
    • OBJECT_CONTENT_TYPE ist der Inhaltstyp des Objekts. Beispiel: image/png.
    • GENERATION ist die beabsichtigte Generierungsnummer des Objekts, das Sie ersetzen. Beispiel: 1122334455667788.
    • BUCKET_NAME ist der Name des Buckets, in den Sie das Objekt hochladen. Beispiel: my-bucket.
    • OBJECT_NAME ist der Name, den Sie dem Objekt geben möchten. Beispiel: dog.png.

Szenarien für die Verwendung von Vorbedingungen

In folgenden Szenarien werden Race-Bedingungen und Caching-Beispiele erläutert, die von der Verwendung von Vorbedingungen profitieren.

Mehrere Anfrageversuche

Cloud Storage ist ein verteiltes System. Da Anfragen aufgrund von Netzwerk- oder Dienstbedingungen fehlschlagen können, sollten Sie bei Neuversuchen nach Fehlschlägen den exponentiellen Backoff verwenden. Aufgrund der Beschaffenheit verteilter Systeme können diese Neuversuche zu unerwartetem Verhalten führen.

Beispiel: Sie möchten das Objekt file.txt löschen, das in einem Ihrer Buckets gespeichert ist. Anschließend möchten Sie ein neues Objekt mit demselben Namen in den Bucket aufnehmen. Hierzu senden Sie eine Anfrage zum Löschen des Objekts. Aufgrund einer Netzwerkbedingung (zum Beispiel ein zwischengeschalteter Router, dessen Verbindung vorübergehend getrennt wird) erreicht die Anfrage jedoch Cloud Storage nicht und Sie erhalten keine Antwort.

Da Sie keine Antwort auf die erste Anfrage erhalten haben, senden Sie eine zweite Anfrage zum Löschen des Objekts. Diese ist erfolgreich und Sie erhalten eine Antwort, die das Löschen bestätigt. Eine Minute später beschließen Sie, eine neue file.txt-Datei hochzuladen. Ihr Upload ist erfolgreich.

Eine Race-Bedingung wird ausgelöst, wenn die Verbindung des zuvor getrennten Routers wiederhergestellt wird und dieser nun Ihre ursprüngliche Anfrage zum Löschen an Cloud Storage sendet. Die Anfrage erreicht Cloud Storage und wird erfolgreich ausgeführt, weil die neue file.txt-Datei vorhanden ist. Cloud Storage sendet eine Antwort, die Sie jedoch nicht erhalten, weil Ihr Client den Vorgang nicht mehr überwacht. Das heißt, es wird nicht nur Ihre neue Datei unerwünscht gelöscht, sondern Sie erfahren auch nichts von dem zweiten Löschvorgang.

Das folgende Diagramm veranschaulicht den Vorgang:

Race-Bedingungen verhindern

Damit die oben beschriebene Situation nicht eintritt, rufen Sie zuerst die Metadaten von file.txt ab, um deren aktuelle Generierung zu ermitteln. Anschließend verwenden Sie die Generierung in einer generation-match-Vorbedingung, die Sie als Teil der Löschanfrage angeben. Aufgrund der Vorbedingung wird nur das Objekt mit dieser spezifischen Generierungsnummer gelöscht. Dies ist unabhängig davon, wann die Löschanfrage Cloud Storage erreicht, oder wie oft die Löschanfrage mit der Vorbedingung gesendet wird. Alle unbeabsichtigten Versuche zum Löschen einer anderen Generierung von file.txt schlagen mit dem Antwortcode 412 Precondition Failed fehl.

Ähnliche Netzwerkunterbrechungen können auch nach der Löschanfrage bei der anschließenden Uploadanfrage Race-Bedingungen auslösen. Viele solche Race-Bedingungen können Sie jedoch vermeiden, wenn Sie in einer in der Upload-Anfrage enthaltenen generation-match-Vorbedingung den Wert 0 verwenden. Diese Vorbedingung gewährleistet, dass bei mehreren Uploadversuchen das Objekt nicht versehentlich zweimal geschrieben wird, weil die Anfrage nur fortfahren darf, wenn keine weiteren aktuellen Generierungen des Objekts vorhanden sind.

Mit diesen Vorbedingungen schützen Sie sich vor Datenverlust, wenn Sie Lösch- und Uploadanfragen ausführen. Das folgende Diagramm veranschaulicht den Vorgang:

Objektmetadatenzuordnung

Die Daten und Metadaten eines Objekts sind separate Entitäten, die das Objekt zusammen in Cloud Storage definieren. Da es separate Entitäten sind, kann es vorkommen, dass die Objektdaten geändert werden, während Sie mit den Objekt-Metadaten arbeiten.

Hier ein paar Beispiele:

  • Sie möchten die Metadaten und Daten für ein Objekt herunterladen, die aus zwei separaten Anfragen von Cloud Storage abgerufen werden müssen. Sie fordern zuerst die Objektmetadaten an, aber bevor Sie die Objektdaten anfordern können, wird das Objekt von einem unabhängigen Prozess oder Nutzer ersetzt. Die Anfrage für die Objektdaten ist weiterhin erfolgreich, aber Sie haben jetzt die Metadaten des alten Objekts und die Daten des neuen Objekts.

  • Sie möchten die Metadaten für ein Objekt aktualisieren und rufen die aktuellen Metadaten für das Objekt ab, um seinen aktuellen Status zu ermitteln. Bevor Sie die Anfrage zum Aktualisieren der Metadaten mit den gewünschten Änderungen senden können, ersetzt ein unabhängiger Prozess oder ein Nutzer das Objekt. Ihre Anfrage zum Ändern der Metadaten für das neue Objekt ist weiterhin erfolgreich, jetzt aber mit anderen Objektdaten verknüpft als beabsichtigt.

Race-Bedingungen verhindern

Damit diese Situationen nicht auftreten, sollten Sie die Generierungsnummer verwenden, die in der ersten Anfrage für Objekt-Metadaten zurückgegeben wurde. Anschließend verwenden Sie diesen Wert in einer generation-match-Vorbedingung in der zweiten Anfrage. Dadurch wird sichergestellt, dass die Metadaten entweder ordnungsgemäß mit den Daten übereinstimmen oder die zweite Anfrage mit dem 412 Precondition Failed-Antwortcode fehlschlägt, sodass Sie die richtigen Metadaten für das neue Objekt anfordern können.

Wenn Sie befürchten, dass sich die Objektmetadaten zwischen der ersten und der zweiten Anfrage ändern könnten, können Sie auch die in der ersten Anfrage enthaltene Meta-Generierungsnummer kopieren und sie in einer Vorbedingung "metageneration-match" in der zweiten Anfrage verwenden.

Aktualität der Lokalen Kopie

Wenn Sie eine lokale Kopie eines in Cloud Storage gespeicherten Objekts haben, ist es oft sinnvoll, dass Ihre lokale Kopie auf dem neuesten Stand der in Ihrem Bucket gespeicherten Kopie bleibt. Wenn sich das in Ihrem Bucket gespeicherte Objekt jedoch nicht ändert, sollten Sie keine Zeit und keine Ressourcen damit verschwenden, es noch einmal herunterladen, insbesondere wenn das Objekt groß ist.

Um unnötige Downloads von Inhalten zu verhindern, die immer noch aktuell sind, können Sie die Generierungsnummer Ihrer lokalen Kopie als Wert in einer generation-not-match-Vorbedingung verwenden, die Sie in Ihre Downloadanfrage aufnehmen:

  • Wenn die Daten in Ihrem Bucket weiterhin mit Ihrer lokalen Kopie übereinstimmen, stimmen die Generierungsnummern überein, wodurch die Vorbedingung fehlschlägt. Deshalb schlägt die Gesamtanfrage mit der Antwort 304 Not Modified fehl und die Daten werden nicht unnötigerweise heruntergeladen.

  • Wenn sich die Daten in Ihrem Bucket geändert haben, stimmen die Generierungsnummern nicht überein und die Vorbedingung ist erfolgreich. Das bedeutet, dass die Gesamtanfrage normal fortgesetzt und die aktualisierte Version des Inhalts heruntergeladen wird.

Nächste Schritte