Le librerie client di Cloud per Java utilizzano i tentativi per gestire errori imprevisti e temporanei (ovvero il server non è temporaneamente disponibile). Più tentativi possono comportare una risposta riuscita dal server.
I valori di ripetizione predefiniti vengono selezionati dal team che gestisce il servizio cloud. Questi valori di nuovi tentativi vengono configurati per RPC. Un servizio può scegliere di attivare i tentativi solo per un sottoinsieme di RPC. È possibile che ogni RPC per un servizio sia configurata in modo diverso.
Parametri per nuovi tentativi
Le librerie client hanno due tipi di parametri di ripetizione da configurare:
- Retry Status Code: insieme di codici di stato su cui riprovare.
- Timeout per i tentativi o limiti dei tentativi:RetrySettings configurabile per definire i limiti.
Posizione predefinita della configurazione dei nuovi tentativi RPC
Le configurazioni di nuovi tentativi predefinite sono definite nel file {Client}StubSettings generato. Utilizzando la RPC ExportAssets in
Java-Asset v3.64.0 come esempio, le configurazioni di nuovi tentativi predefinite sono definite
nei seguenti punti:
Retry Status Codes: configurato nel file
AssetServiceStubSettings.java. Esempio:ImmutableMap.Builder<String, ImmutableSet<StatusCode.Code>> definitions = ImmutableMap.builder(); definitions.put("no_retry_0_codes", ImmutableSet.copyOf(Lists.<StatusCode.Code>newArrayList())); // ... More StatusCode configurations RETRYABLE_CODE_DEFINITIONS = definitions.build();Parametri per i nuovi tentativi:configurati nel file
AssetServiceStubSettings.java. Esempio:ImmutableMap.Builder<String, RetrySettings> definitions = ImmutableMap.builder(); RetrySettings settings = null; settings = RetrySettings.newBuilder() .setInitialRpcTimeoutDuration(Duration.ofMillis(60000L)) .setRpcTimeoutMultiplier(1.0) .setMaxRpcTimeoutDuration(Duration.ofMillis(60000L)) .setTotalTimeoutDuration(Duration.ofMillis(60000L)) .build(); definitions.put("no_retry_0_params", settings); // ... More RetrySettings configurations RETRY_PARAM_DEFINITIONS = definitions.build();
Entrambe le configurazioni sono mappate all'RPC nel file
AssetServiceStubSettings.java. Esempio:
builder
.exportAssetsSettings()
.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes"))
.setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params"));
Concetti di ripetizione della libreria client
L'abilitazione dei tentativi consente a una RPC di effettuare più tentativi per ottenere una chiamata
riuscita. Una chiamata riuscita è una risposta di un server che restituisce un codice di stato OK (da gRPC) o un codice di stato 2xx (da HttpJson).
Tentativo e operazione
La seguente configurazione di RetrySettings modifica le impostazioni di riprova sia per
il tentativo che per l'operazione di una chiamata RPC:
settings =
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(100L))
.setRetryDelayMultiplier(1.3)
.setMaxRetryDelayDuration(Duration.ofMillis(60000L))
.setInitialRpcTimeoutDuration(Duration.ofMillis(60000L))
.setRpcTimeoutMultiplier(1.0)
.setMaxRpcTimeoutDuration(Duration.ofMillis(60000L))
.setTotalTimeoutDuration(Duration.ofMillis(60000L))
.build();
Un tentativo RPC è il singolo tentativo effettuato e un'operazione RPC è un insieme di tutti i tentativi effettuati. Una singola chiamata RPC avrà uno o più tentativi in una singola operazione.
I limiti RPC individuali (un tentativo) sono controllati dalle seguenti impostazioni:
setInitialRetryDelayDuration: ritardo prima del primo tentativo.setRetryDelayMultiplier: moltiplicatore del ritardo applicato tra un tentativo e l'altro.setMaxRetryDelayDuration: ritardo massimo possibile per un tentativo.setInitialRpcTimeoutDuration: timeout per il primo tentativo.setRpcTimeoutMultiplier: moltiplicatore del timeout applicato tra un tentativo e l'altro.setMaxRpcTimeoutDuration: timeout massimo possibile per un tentativo.
I limiti RPC totali (un'operazione) sono controllati dalle seguenti impostazioni:
setTotalTimeout: Timeout totale consentito per l'intera operazione.setMaxAttempts: Numero massimo di tentativi consentiti.
Quando viene eseguito un nuovo tentativo di RPC
Un RPC verrà ritentato quando si verificano entrambi gli scenari seguenti:
- La libreria riceve un codice di stato non riuscito e il codice di stato è contrassegnato come riprovabile.
- L'invocazione di una RPC supera i limiti della singola RPC, ma rientra comunque nei limiti totali delle RPC.
Se solo uno scenario è vero o se nessuno dei due è vero, la RPC non verrà ritentata.
Ad esempio, se il timeout totale non è stato superato, ma l'ultimo tentativo riceve un codice di stato che non può essere riprovato.
Inoltre, quando configuri i limiti RPC, puoi configurare i limiti per ogni tentativo, nonché i limiti RPC totali. L'algoritmo di ripetizione garantirà che i limiti di un singolo tentativo rientrino nei limiti totali della RPC.
Backoff esponenziale
Il backoff esponenziale ripeterà le richieste con un ritardo crescente tra un tentativo e l'altro. Questo valore di ritardo dei tentativi può essere limitato con un valore massimo di ritardo dei tentativi.
Ad esempio, le seguenti configurazioni di nuovi tentativi possono comportare i seguenti tempi di ritardo:
Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
- Tentativo 1: ritardo di 100 ms
- Tentativo 2: ritardo di 200 ms
- Tentativo 3: ritardo di 400 ms
- Tentativo 4: ritardo di 500 ms
- …
- Tentativo X: ritardo di 500 ms
Jitter
Il jitter è una varianza aggiuntiva che utilizza la casualità per distribuire il momento in cui vengono richiamate le RPC. Google Cloud Le librerie client attivano sempre il jitter per i tentativi. In questo modo, i tentativi di ripetizione vengono distribuiti senza sovraccaricare il server.
Il valore casuale di jitter viene calcolato in base al ritardo di ripetizione. Prima di ogni
tentativo, l'algoritmo di ripetizione calcola un valore casuale compreso tra
[1, RETRY_DELAY]. Questo valore calcolato è il ritardo approssimativo prima che la
richiesta venga inviata al server.
Le seguenti configurazioni di nuovi tentativi utilizzano il jitter e il backoff esponenziale.
Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
Ciò potrebbe comportare i seguenti tempi di ritardo:
- Tentativo 1: ritarda un valore casuale compreso tra
[1, 100]ms - Tentativo 2: ritarda un valore casuale compreso tra
[1, 200]ms - Tentativo 3: ritarda un valore casuale compreso tra
[1, 400]ms - Tentativo 4: ritarda un valore casuale compreso tra
[1, 500]ms - …
- Tentativo X: ritarda un valore casuale compreso tra
[1, 500]ms
Esempi di nuovi tentativi
Gli esempi seguenti mostrano il comportamento di alcune configurazioni di nuovi tentativi.
Nessun nuovo tentativo
Questo esempio disabilita i tentativi.
RetrySettings defaultNoRetrySettings =
RetrySettings.newBuilder()
// Use the default configurations for other settings
.setTotalTimeoutDuration(Duration.ofMillis(5000L))
// Explicitly set retries as disabled (maxAttempts == 1)
.setMaxAttempts(1)
.build();
In alternativa, questo comportamento può essere configurato con questo esempio:
RetrySettings defaultNoRetrySettings =
RetrySettings.newBuilder()
.setLogicalTimeoutDuration(Duration.ofMillis(5000L))
.build();
La seguente tabella mostra i tentativi:
| Numero di tentativo | Timeout RPC | Intervallo tra tentativi | Chiamata richiamata | Chiamata terminata |
|---|---|---|---|---|
| 1 | 5000ms | 0ms | 0ms | 5000ms |
Esempio di riprova
Questo esempio consente di riprovare con ritardi e timeout specificati.
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(200L))
.setRetryDelayMultiplier(2.0)
.setMaxRetryDelayDuration(Duration.ofMillis(500L))
.setInitialRpcTimeoutDuration(Duration.ofMillis(1500L))
.setRpcTimeoutMultiplier(2.0)
.setMaxRpcTimeoutDuration(Duration.ofMillis(3000L))
.setTotalTimeoutDuration(Duration.ofMillis(5000L))
.build();
La seguente tabella mostra i tentativi:
| Numero di tentativo | Timeout RPC | Intervallo tra tentativi | Chiamata richiamata | Chiamata terminata |
|---|---|---|---|---|
| 1 | 1500ms | 0ms | 0ms | 1500ms |
| 2 (Riprova) | 3000ms | 200 ms | 1700ms | 4700ms |
| 3 (Nuovo tentativo non eseguito) | - | 400 ms | - | - |
Esempio di nuovo tentativo: timeout totale più lungo
Questo esempio è simile al primo esempio di nuovo tentativo, ma ha un timeout totale più lungo per mostrare un ulteriore tentativo e il timeout RPC limitato per l'ultimo tentativo.
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(200L))
.setRetryDelayMultiplier(2.0)
.setMaxRetryDelayDuration(Duration.ofMillis(500L))
.setInitialRpcTimeoutDuration(Duration.ofMillis(1500L))
.setRpcTimeoutMultiplier(2.0)
.setMaxRpcTimeoutDuration(Duration.ofMillis(3000L))
.setTotalTimeoutDuration(Duration.ofMillis(10000L))
.build();
La seguente tabella mostra i tentativi:
| Numero di tentativo | Timeout RPC | Intervallo tra tentativi | Chiamata richiamata | Chiamata terminata |
|---|---|---|---|---|
| 1 | 1500ms | 0ms | 0ms | 1500ms |
| 2 (Riprova) | 3000ms | 200 ms | 1700ms | 4700ms |
| 3 (Riprova) | 4900ms | 400 ms | 5100ms | 10.000 ms |
Il terzo valore di timeout RPC per i nuovi tentativi è limitato a causa del valore di timeout totale. L'utilizzo del moltiplicatore (2.0) con il valore di timeout precedente (3000 ms) comporta un timeout RPC di 6000 ms. Tuttavia, il timeout RPC non deve superare il timeout totale e viene ridotto al "tempo rimanente" (10000 - 5100 = 4900).
Esempio di nuovo tentativo: timeout RPC limitato
RetrySettings defaultRetrySettings =
RetrySettings.newBuilder()
.setInitialRetryDelayDuration(Duration.ofMillis(200L))
.setRetryDelayMultiplier(2.0)
.setMaxRetryDelayDuration(Duration.ofMillis(500L))
.setInitialRpcTimeoutDuration(Duration.ofMillis(500L))
.setRpcTimeoutMultiplier(2.0)
.setMaxRpcTimeoutDuration(Duration.ofMillis(2000L))
.setTotalTimeoutDuration(Duration.ofMillis(4000L))
.build();
La seguente tabella mostra i tentativi:
| Numero di tentativo | Timeout RPC | Intervallo tra tentativi | Chiamata richiamata | Chiamata terminata |
|---|---|---|---|---|
| 1 | 500 ms | 0ms | 0ms | 500 ms |
| 2 (Riprova) | 1000ms | 200 ms | 700 ms | 1700ms |
| 3 (Riprova) | 1900ms | 400 ms | 2100ms | 4000ms |
Un altro esempio in cui il timeout RPC è limitato per non superare il timeout totale.
Come configurare parametri di ripetizione personalizzati per una RPC
L'esempio seguente utilizza la libreria client Java-Asset:
Crea la classe
RetrySettingscon le tue configurazioni personalizzate:RetrySettings customRetrySettings = RetrySettings.newBuilder() // ... Retry Configurations .build(); RetrySettings customRetrySettings2 = RetrySettings.newBuilder() // ... Retry Configurations .build();Crea
StubSettings.Builderper il tuo client e configuralo per RPC:AssetServiceStubSettings.Builder assetStubSettingsBuilder = AssetServiceStubSettings.newBuilder(); assetStubSettingsBuilder .exportAssetsSettings() // Set your custom Retry Settings .setRetrySettings(customRetrySettings) // Set your custom Retryable Codes .setRetryableCodes(ImmutableSet.of(StatusCode.Code.DEADLINE_EXCEEDED));Lo snippet di codice fornito imposta configurazioni di nuovi tentativi personalizzate per la RPC
ExportAssetsdiAssetServiceClient. Configura la RPCExportAssetsin modo che utilizzi le impostazioni di riprova configurate incustomRetrySettingse imposta i codici che possono essere riprovati suDEADLINE_EXCEEDED.Crea le impostazioni per il cliente come
assetSettings:java AssetServiceSettings assetSettings = AssetServiceSettings.create(assetStubSettingsBuilder.build());4.Crea il cliente con le impostazioni comeassetClient.java try (AssetServiceClient assetClient = AssetServiceClient.create(assetSettings)) { ... }
Ripeti il passaggio 2 per ogni RPC da configurare. Ad esempio:
AssetServiceStubSettings.Builder assetStubSettingsBuilder = AssetServiceStubSettings.newBuilder();
// Modify the retry params for ExportAssets RPC
assetStubSettingsBuilder
.exportAssetsSettings()
.setRetrySettings(customRetrySettings)
.setRetryableCodes(ImmutableSet.of(StatusCode.Code.DEADLINE_EXCEEDED));
// Modify the retry params for ListAssets RPC
assetStubSettingsBuilder
.listAssetsSettings()
.setRetrySettings(customRetrySettings2)
.setRetryableCodes(ImmutableSet.of(StatusCode.Code.UNAVAILABLE));
Domande frequenti
Di seguito sono riportate le domande più frequenti relative al comportamento di ripetizione dei tentativi del client.
Mi aspettavo X tentativi, ma ne sono stati effettuati Y.
A meno che tu non specifichi esplicitamente il numero massimo di tentativi (e disattivi le configurazioni del timeout), potresti non visualizzare sempre lo stesso numero di tentativi di ripetizione. I valori casuali di jitter per il ritardo RPC rendono difficile prevedere quando viene effettivamente inviata la richiesta.
La chiamata RPC ha restituito un errore prima che venisse raggiunto il valore di timeout totale.
L'algoritmo di ripetizione calcolerà il valore del ritardo di ripetizione jitterato durante ogni
tentativo di ripetizione. Il ritardo di ripetizione calcolato verrà pianificato per l'esecuzione in futuro
(ovvero currentTime() + jitteredRetryDelay). Se l'ora del tentativo pianificato
supera il timeout totale, l'ultimo tentativo non verrà eseguito.
Ho configurato impostazioni personalizzate e riscontro problemi con le quote.
Potresti aver configurato RetrySettings per l'esecuzione in modo troppo aggressivo. I valori di
nuovo tentativo predefiniti vengono scelti dal team che gestisce il servizio.
Valuta la possibilità di aumentare il ritardo tra i tentativi (ritardo iniziale e moltiplicatore dei tentativi) in modo che i tentativi siano più distanziati e meno frequenti. Tieni presente che ciò può comportare una risposta più lenta.
Il tuo caso d'uso può richiedere una risposta più rapida o tentativi di ripetizione più frequenti, o entrambi. In questo caso, prova ad aumentare i limiti di quota.