Condizioni preliminari per le richieste

In questa pagina vengono descritte le condizioni preliminari per le richieste, che puoi utilizzare per evitare le richieste dall'applicazione a una risorsa quando questa si trova in uno stato imprevisto.

Introduzione

Quando vengono utilizzate le precondizioni in una richiesta a Cloud Storage, continua solo se la risorsa scelta come target soddisfa i criteri definiti nella precondizioni. I controlli dei prerequisiti assicurano che un bucket o un oggetto sia nello stato previsto, consentendo di eseguire aggiornamenti di lettura, modifica e scrittura sicuri e operazioni condizionali.

Le condizioni preliminari vengono spesso utilizzate per evitare le condizioni di gara nelle richieste con mutazioni, come caricamenti, eliminazioni o aggiornamenti dei metadati. Le condizioni di gara possono verificarsi quando la stessa richiesta viene inviata ripetutamente o quando processi indipendenti tentano ciascuno di modificare la stessa risorsa. Per ulteriori informazioni, consulta Esempi di condizioni di gara e corruzione dei dati. Le precondizioni vengono spesso utilizzate anche quando si recuperano i metadati degli oggetti e dati nelle richieste successive, per garantire che l'oggetto non sia cambiato nel tempo tra le due richieste.

Criteri di precondizione

Cloud Storage supporta l'utilizzo di diverse risorse immutabili proprietà in condizioni preliminari:

Nella tabella seguente sono elencate le condizioni preliminari supportate dall'API JSON e dall'API XML:

API JSON API XML Descrizione
Parametro di query ifGenerationMatch Intestazione x-goog-if-generation-match La richiesta procede se il valore generation della risorsa di destinazione corrisponde al valore utilizzato nella condizione preliminare. Se i valori non corrispondono, la richiesta non va a buon fine e viene restituita una risposta 412 Precondition Failed.
Parametro di query ifMetagenerationMatch Intestazione x-goog-if-metageneration-match La richiesta procede se metageneration della risorsa di destinazione corrisponde al valore utilizzato nel precondizionale. Se i valori non corrispondono, la richiesta non va a buon fine e viene restituita una risposta 412 Precondition Failed.
Parametro di query ifGenerationNotMatch N/D La richiesta procede se generation della risorsa di destinazione non corrisponde al valore utilizzato nel precondizionale. Se i valori corrispondono, la richiesta non va a buon fine con una risposta 304 Not Modified.
Parametro di query ifMetagenerationNotMatch N/D La richiesta procede se metageneration della risorsa di destinazione non corrisponde al valore utilizzato nel precondizionale. Se i valori corrispondono, la richiesta non riesce e restituisce una risposta 304 Not Modified.
Intestazione If-Match Intestazione If-Match Applicabile alle richieste che recuperano i dati. La richiesta procede se il valore ETag della risorsa di destinazione corrisponde al valore utilizzato nella condizione preliminare. Se i valori non corrispondono, la richiesta non va a buon fine e viene inviata una risposta 412 Precondition Failed.
Intestazione If-None-Match Intestazione If-None-Match Applicabile alle richieste che recuperano i dati. La richiesta procede se il valore ETag della risorsa di destinazione non corrisponde al valore utilizzato nella condizione preliminare. Se i valori corrispondono, la richiesta non va a buon fine con una risposta 304 Not Modified.
N/D Intestazione If-Modified-Since La richiesta procede se la risorsa di destinazione ha una data Last-Modified successiva al valore utilizzato nella condizione preliminare. Se la risorsa di destinazione non soddisfa questa condizione preliminare, la richiesta non va a buon fine e viene inviata una risposta 304 Not Modified.
N/D Intestazione If-Unmodified-Since La richiesta procede se la risorsa di destinazione ha una data Last-Modified precedente o uguale al valore utilizzato nel prerequisito. Se la risorsa di destinazione non soddisfa questo prerequisito, la richiesta non va a buon fine e viene restituita una risposta 412 Precondition Failed.

Precondizioni della composizione dell'oggetto

Quando esegui la composizione di oggetti, sia l'API JSON sia l'API XML supportano quanto segue:

  • Le precondizioni di corrispondenza alla generazione e alla metagenerazione per l'oggetto di destinazione.

  • La precondizione di corrispondenza alla generazione per ogni oggetto di origine. L'utilizzo di questo prerequisito impedisce l'utilizzo di componenti errati nel caso in cui un processo indipendente sovrascriva uno dei componenti previsti della composizione. Se utilizzi i prerequisiti e si verifica una sovrascrittura di questo tipo, le operazioni compose non vanno a buon fine con una risposta 412 Precondition Failed.

Precondizioni per la copia degli oggetti

Quando copi o riscrivi un oggetto in Cloud Storage, sia l'API JSON sia l'API XML supportano l'utilizzo di prerequisiti standard per l'oggetto di destinazione. Ogni API dispone di un supporto aggiuntivo per la condizione preliminare per l'origine oggetti:

  • L'API JSON supporta le precondizioni di generazione e metagenerazione per il , che vengono specificati mediante parametri di ricerca preceduti da un prefisso con ifSource.

  • Tutte le condizioni preliminari supportate dall'API XML possono essere utilizzate per l'oggetto di origine. Questi prerequisiti sono specificati nelle intestazioni con prefisso x-goog-copy-source-.

Il valore 0 in un prerequisito di corrispondenza alla generazione

La precondizione per la corrispondenza di generazione accetta il valore 0 come caso speciale. Quando una precondizione per la corrispondenza di generazione con un valore pari a 0 è inclusa in una richiesta la richiesta continua solo se non esiste alcun oggetto con il nome specificato nel o se sono presenti solo versioni non correnti dell'oggetto nel bucket. Se esiste una versione live con il nome specificato, la richiesta ha esito negativo con codice di stato 412 Precondition Failed.

Best practice e considerazioni

  • Puoi utilizzare più prerequisiti in una singola richiesta. Se uno dei le condizioni preliminari non sono soddisfatte, la richiesta complessiva non riesce.

  • I bucket non hanno un numero di generazione, anche se hanno un numero di metagenerazione. Non devi utilizzare condizioni preliminari che specificano numero di generazione in una richiesta di bucket.

  • Se utilizzi una precondizione di metagenerazione in una richiesta di oggetto, devi usa sempre anche una precondizione di generazione. In questo modo, la richiesta non andrà a buon fine su un altro oggetto che per coincidenza ha un numero di metagenerazione che soddisfa la precondizione.

  • Per i bucket che hanno versioni dell'oggetto attive e non attuali, le richieste di oggetti non si applicano alle versioni non correnti, a meno che non venga numero è esplicitamente incluso nella richiesta. Ciò significa che, richiesta generica che utilizza le precondizioni, la richiesta non va a buon fine se la versione non soddisfa la condizione preliminare, indipendentemente dal fatto che un indirizzo che soddisfi le precondizioni.

  • In genere, dovresti utilizzare i prerequisiti di generazione e metagenerazione anziché quelli ETag. I numeri di generazione e metagenerazione monitorano insieme tutti gli aggiornamenti degli oggetti, incluse le modifiche ai metadati, offrendo una garanzia più solida rispetto agli ETag. Inoltre, i numeri di generazione e metagenerazione sono uniformi tra le API, mentre gli ETag non lo sono.

  • Le condizioni preliminari non possono essere utilizzate nei caricamenti multiparte dell'API XML. Tentativo questo comporta l'errore 400 NotImplemented.

Costo delle precondizioni

Molte architetture che utilizzano i prerequisiti richiedono di effettuare una richiesta di metadati dell'oggetto prima della richiesta principale per determinare il numero di generazione e/o metagenerazione corrente:

  • Se ricevi una richiesta aggiuntiva, puoi raddoppiare la porzione di rete latenza complessiva delle operazioni aggiungendo un ulteriore andata e ritorno, che potrebbe essere è un fattore importante nelle operazioni sensibili alla latenza.

A seconda dell'applicazione, ci sono modi per ridurre l'impatto dell'utilizzo precondizioni come:

  • Memorizza localmente i numeri di generazione e metagenerazione degli oggetti in modo da conoscere già i numeri corretti da utilizzare nel precondizionatore.
  • Avere conoscenza dell'applicazione degli oggetti appena creati, in modo da sapere già quando utilizzare la precondizione if-generation-match:0.

Esempio: utilizzo di un precondizione

L'esempio seguente utilizza la precondizione per la corrispondenza di generazione in una richiesta per caricare un oggetto. Affinché la richiesta venga eseguita, nel bucket deve essere memorizzato un oggetto preesistente con il nome specificato e il numero di generazione dell'oggetto preesistente deve corrispondere al numero fornito nel prerequisito:

Riga di comando

Utilizza il flag --if-generation-match insieme al comando normale:

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

Dove:

  • GENERATION è il numero di generazione previsto dell'oggetto che stai sostituendo. Ad esempio, 1122334455667788.

  • OBJECT_LOCATION è il percorso locale dell'oggetto. Ad esempio, Desktop/dog.png.

  • DESTINATION_BUCKET_NAME è il nome del bucket in cui carichi l'oggetto. Ad esempio, my-bucket.

API JSON

  1. Avere installato e inizializzato gcloud CLI per generare un token di accesso per l'intestazione Authorization.

    In alternativa, puoi creare un token di accesso utilizzando il metodo OAuth 2.0 Playground e includilo nell'intestazione Authorization.

  2. Utilizza cURL per chiamare l'API JSON con una richiesta di oggetto POST:

    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"

    Dove:

    • OBJECT_LOCATION è il percorso locale dell'oggetto. Ad esempio, Desktop/dog.png.
    • OBJECT_CONTENT_TYPE è il tipo di contenuti dell'oggetto. Ad esempio, image/png.
    • BUCKET_NAME è il nome del bucket in cui stai caricando l'oggetto. Ad esempio, my-bucket.
    • OBJECT_NAME è il nome che vuoi assegnare al tuo . Ad esempio, dog.png.
    • GENERATION è il numero di generazione previsto dell'oggetto che stai sostituendo. Ad esempio, 1122334455667788.

API XML

  1. Avere installato e inizializzato gcloud CLI per generare un token di accesso per l'intestazione Authorization.

    In alternativa, puoi creare un token di accesso utilizzando OAuth 2.0 Playground e includerlo nell'intestazione Authorization.

  2. Utilizza cURL per chiamare l'API XML con una richiesta di PUT Object:

    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"

    Dove:

    • OBJECT_LOCATION è il percorso locale dell'oggetto. Ad esempio, Desktop/dog.png.
    • OBJECT_CONTENT_TYPE è il tipo di contenuti dell'oggetto. Ad esempio, image/png.
    • GENERATION è il numero di generazione previsto dell'oggetto che stai sostituendo. Ad esempio, 1122334455667788.
    • BUCKET_NAME è il nome del bucket in cui stai caricando l'oggetto. Ad esempio, my-bucket.
    • OBJECT_NAME è il nome che vuoi assegnare all'oggetto. Ad esempio, dog.png.

Scenari per l'utilizzo dei prerequisiti

Gli scenari seguenti esplorano le condizioni di gara ed esempi di memorizzazione nella cache che possono trarre vantaggio dall'uso di condizioni preliminari.

Nuovi tentativi di richiesta multipli

Cloud Storage è un sistema distribuito. Poiché le richieste possono non andare a buon fine condizioni di rete o di servizio, il modo consigliato per riprovare gli errori è backoff esponenziale. Tuttavia, a causa della natura di deployment sistemi, a volte questi nuovi tentativi possono causare comportamenti sorprendenti.

Considera il seguente caso: vuoi eliminare un oggetto, file.txt, archiviato uno dei tuoi bucket. In seguito vorrai aggiungere un nuovo oggetto con lo stesso nome al bucket. A questo scopo, devi inviare una richiesta di eliminazione per eliminare il . Tuttavia, una condizione della rete, ad esempio la perdita temporanea della connettività di un router intermedio, impedisce alla richiesta di raggiungere Cloud Storage e non ricevi una risposta.

Poiché non hai ricevuto una risposta alla prima richiesta, ne invii una seconda per l'eliminazione dell'oggetto, che va a buon fine e ricevi una risposta che conferma l'eliminazione. Un minuto dopo, carichi un nuovo file.txt e il caricamento va a buon fine.

Si verifica una condizione di gara se il router che ha perso la connettività la recupera successivamente e invia la richiesta di eliminazione originale, apparentemente persa, a Cloud Storage. Quando la richiesta arriva a Cloud Storage, operazione riuscita perché è presente un nuovo file.txt. Cloud Storage invia una risposta che non ricevi perché il client ha smesso di ascoltarla. Il nuovo file non viene solo eliminato, contrariamente alle tue intenzioni, ma anche non sai che si è verificata la seconda eliminazione.

Il seguente diagramma mostra cosa è successo:

Prevenzione della race condition

Per evitare che si verifichi la situazione di cui sopra, dovresti iniziare a ottenere lo metadati per file.txt al fine di determinarne la generazione attuale. Poi utilizza la generazione in una precondizione di corrispondenza di generazione che includi come parte della richiesta di eliminazione. La condizione preliminare garantisce che solo l'oggetto con quell'oggetto un numero di generazione specifico viene eliminato, indipendentemente da quando è stata richiesta raggiunge Cloud Storage o quante volte la richiesta di eliminazione viene inviata la precondizione. Eventuali tentativi involontari di eliminare una generazione diversa di file.txt non riesce con il codice di risposta 412 Precondition Failed.

Poiché interruzioni della rete simili potrebbero causare condizioni di gara per la richiesta di caricamento che ha seguito la richiesta di eliminazione, puoi evitare molte di queste condizioni di gara utilizzando il valore 0 in una precondizione di corrispondenza alla generazione inclusa nella richiesta di caricamento. L'uso di questa condizione preliminare garantisce che i nuovi tentativi non scrivano accidentalmente due volte l'oggetto perché la precondizione consente di proseguire la richiesta solo se non esistono generazioni attuali dell'oggetto.

Con questi prerequisiti, proteggi i tuoi dati da una perdita accidentale quando esegui le richieste di eliminazione e caricamento. Come mostrato nel seguente diagramma:

Associazione dei metadati degli oggetti

I dati e i metadati di un oggetto sono entità distinte che insieme definiscono l'oggetto in Cloud Storage. Poiché esistono separatamente, è possibile che i dati dell'oggetto cambino mentre lavori con i metadati dell'oggetto.

Considera i seguenti casi:

  • Vuoi scaricare i metadati e i dati di un oggetto, che devono essere recuperati da Cloud Storage in due richieste distinte. Hai richiesto dei metadati dell'oggetto, ma prima di poter richiedere i dati dell'oggetto, l'oggetto viene sostituito da un processo indipendente o da un utente. La tua richiesta dei dati dell'oggetto ha ancora esito positivo, ma ora hai i metadati vecchio oggetto e i dati di quello nuovo.

  • Vuoi aggiornare i metadati per un oggetto, in modo da recuperare lo stato attuale metadati per l'oggetto al fine di determinarne lo stato attuale. Prima di poter inviare la richiesta di aggiornamento dei metadati con le modifiche desiderate, da un processo indipendente o da un utente. La tua richiesta di modifica dei metadati per il nuovo oggetto è ancora valida, ma ora è associata a dati dell'oggetto diversi da quelli previsti.

Prevenzione della race condition

Per evitare che si verifichino queste situazioni, è necessario utilizzare il numero di generazione che viene restituito nella richiesta iniziale per i metadati dell'oggetto, in una precondizione di corrispondenza di generazione nella seconda richiesta. Ciò garantisce i metadati corrispondano correttamente ai dati o la seconda richiesta non riesce con un codice di risposta 412 Precondition Failed, che ti consente di richiedere i metadati corretti per il nuovo oggetto.

Se temi che i metadati dell'oggetto possano cambiare tra il primo e seconda richiesta, puoi anche copiare il numero di metagenerazione trovato nella e utilizzarla in una precondizione di corrispondenza di metagenerazione nella seconda richiesta.

Aggiornamento della copia locale

Se hai una copia locale di un oggetto archiviato in Cloud Storage, spesso vuoi che la copia locale sia sempre aggiornata e la copia archiviata nel bucket. Tuttavia, se l'oggetto archiviato nel bucket non cambia, non è consigliabile perdere tempo e risorse scaricandolo di nuovo, soprattutto se l'oggetto è di grandi dimensioni.

Per evitare download inutili di contenuti ancora attuali, puoi utilizzare lo numero di generazione della copia locale come valore in un valore di generazione non corrispondente precondizione, che includi nella richiesta di download:

  • Se i dati nel bucket continuano a corrispondere alla copia locale, la generazione numeri corrispondenti, causando il mancato superamento della condizione preliminare. Di conseguenza, la richiesta complessiva non va a buon fine con una risposta 304 Not Modified e i dati non vengono scaricati inutilmente.

  • Se i dati nel bucket sono cambiati, i numeri di generazione non corrispondono e il prerequisito va a buon fine. Ciò significa che la richiesta complessiva procede normalmente e scarica la versione aggiornata dei contenuti.

Passaggi successivi