Le librerie client Cloud per Java utilizzano i nuovi tentativi per gestire errori imprevisti e temporanei (ovvero il server non è disponibile temporaneamente). Più tentativi possono comportare una risposta riuscita dal server.
I valori predefiniti per i nuovi tentativi vengono selezionati dal team che gestisce il servizio cloud. Questi valori vengono configurati per RPC. Un servizio può scegliere di abilitare i nuovi 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 per i nuovi tentativi da configurare:
- Codice di stato per i nuovi tentativi: insieme di codici di stato per i nuovi tentativi.
- Timeout per i nuovi tentativi o limiti dei tentativi: RetrySettings configurabili per definire i limiti.
Posizione della configurazione predefinita per i nuovi tentativi RPC
Le configurazioni predefinite per i nuovi tentativi sono definite nel file {Client}StubSettings generato. Utilizzando come esempio l'RPC ExportAssets in Java-Asset v3.64.0, le configurazioni predefinite per i nuovi tentativi sono definite nei seguenti punti:
Codici di stato per i nuovi tentativi: configurati 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 relativi ai nuovi tentativi della libreria client
L'abilitazione dei nuovi tentativi consente a un RPC di provare più volte a eseguire una chiamata riuscita. Una chiamata riuscita è una risposta da 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 RetrySettings modifica le impostazioni per i nuovi tentativi sia per il tentativo che per l'operazione di un 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 è una raccolta 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 di ritardo applicato tra un tentativo e l'altro.setMaxRetryDelayDuration: ritardo massimo possibile per un tentativo.setInitialRpcTimeoutDuration: timeout per il primo tentativo.setRpcTimeoutMultiplier: moltiplicatore di 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:
setTotalTimeoutDuration: timeout totale consentito per l'intera operazione.setMaxAttempts: numero massimo di tentativi consentiti.
Quando viene eseguito un nuovo tentativo di un RPC
Verrà eseguito un nuovo tentativo di un RPC quando si verificano entrambi i seguenti scenari:
- La libreria riceve un codice di stato non riuscito e il codice di stato è contrassegnato come riprovabile.
- Una chiamata RPC supera i limiti RPC individuali, ma rientra comunque nei limiti RPC totali.
Se è vero solo uno scenario o se nessuno dei due scenari è vero, non verrà eseguito un nuovo tentativo dell'RPC.
Ad esempio, se il timeout totale non è stato superato, ma l'ultimo tentativo riceve un codice di stato per il quale non è possibile eseguire un nuovo tentativo.
Inoltre, quando configuri i limiti RPC, puoi configurare i limiti per ogni tentativo e i limiti RPC totali. L'algoritmo per i nuovi tentativi garantisce che i limiti di un singolo tentativo rientrino nei limiti RPC totali.
Backoff esponenziale
Il backoff esponenziale eseguirà nuovi tentativi per le richieste con un ritardo crescente tra un tentativo e l'altro. Questo valore di ritardo per i nuovi tentativi può essere limitato con un valore di ritardo massimo per i nuovi tentativi.
Ad esempio, le seguenti configurazioni per i 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
Tremolio
Il tremolio è una variazione aggiunta utilizzando la casualità per distribuire il momento in cui vengono chiamati gli RPC. invoked. Google Cloud Le librerie client abilitano sempre il tremolio per i nuovi tentativi. In questo modo, i tentativi vengono distribuiti senza sovraccaricare il server.
Il valore casuale del tremolio viene calcolato in base al ritardo per i nuovi tentativi. Prima di ogni tentativo, l'algoritmo per i nuovi tentativi 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 per i nuovi tentativi utilizzano il tremolio e il backoff esponenziale.
Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
Questo potrebbe comportare i seguenti tempi di ritardo:
- Tentativo 1: ritardo di un valore casuale compreso tra
[1, 100]ms - Tentativo 2: ritardo di un valore casuale compreso tra
[1, 200]ms - Tentativo 3: ritardo di un valore casuale compreso tra
[1, 400]ms - Tentativo 4: ritardo di un valore casuale compreso tra
[1, 500]ms - …
- Tentativo X: ritardo di un valore casuale compreso tra
[1, 500]ms
Esempi di nuovi tentativi
Gli esempi seguenti mostrano il comportamento di alcune configurazioni per i nuovi tentativi.
Nessun nuovo tentativo
Questo esempio disattiva i nuovi 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 tabella seguente mostra i tentativi:
| Numero di tentativi | Timeout RPC | Ritardo per i nuovi tentativi | Chiamata chiamata | Chiamata terminata |
|---|---|---|---|---|
| 1 | 5000ms | 0ms | 0ms | 5000ms |
Esempio di nuovi tentativi
Questo esempio abilita i nuovi tentativi 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 tabella seguente mostra i tentativi:
| Numero di tentativi | Timeout RPC | Ritardo per i nuovi tentativi | Chiamata chiamata | Chiamata terminata |
|---|---|---|---|---|
| 1 | 1500ms | 0ms | 0ms | 1500ms |
| 2 (nuovo tentativo) | 3000ms | 200ms | 1700ms | 4700ms |
| 3 (nuovo tentativo non eseguito) | - | 400ms | - | - |
Esempio di nuovi tentativi: timeout totale più lungo
Questo esempio è simile al primo esempio di nuovi tentativi, ma ha un timeout totale più lungo per mostrare un tentativo aggiuntivo 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 tabella seguente mostra i tentativi:
| Numero di tentativi | Timeout RPC | Ritardo per i nuovi tentativi | Chiamata chiamata | Chiamata terminata |
|---|---|---|---|---|
| 1 | 1500ms | 0ms | 0ms | 1500ms |
| 2 (nuovo tentativo) | 3000ms | 200ms | 1700ms | 4700ms |
| 3 (nuovo tentativo) | 4900ms | 400ms | 5100ms | 10000ms |
Il valore del timeout RPC del terzo tentativo è limitato dal valore del 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 nuovi tentativi: 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 tabella seguente mostra i tentativi:
| Numero di tentativi | Timeout RPC | Ritardo per i nuovi tentativi | Chiamata chiamata | Chiamata terminata |
|---|---|---|---|---|
| 1 | 500ms | 0ms | 0ms | 500ms |
| 2 (nuovo tentativo) | 1000ms | 200ms | 700ms | 1700ms |
| 3 (nuovo tentativo) | 1900ms | 400ms | 2100ms | 4000ms |
Un altro esempio in cui il timeout RPC è limitato per non superare il timeout totale.
Come configurare parametri personalizzati per i nuovi tentativi per un 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 client e configurarlo per l'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 personalizzate per i nuovi tentativi per l'RPC
ExportAssetsdiAssetServiceClient. Configura l'RPCExportAssetsin modo che utilizzi le impostazioni per i nuovi tentativi configurate incustomRetrySettingse imposta i codici per i quali è possibile eseguire nuovi tentativi suDEADLINE_EXCEEDED.Crea le impostazioni per il client come
assetSettings:AssetServiceSettings assetSettings = AssetServiceSettings.create(assetStubSettingsBuilder.build());Crea il client con le impostazioni come
assetClient.try (AssetServiceClient assetClient = AssetServiceClient.create(assetSettings)) { ... }
Ripeti il passaggio 2 per ogni RPC che vuoi 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 frequenti sul comportamento dei nuovi tentativi del client.
Mi aspettavo X tentativi, ma ne sono stati eseguiti Y.
A meno che tu non specifichi esplicitamente il numero massimo di tentativi (oltre a disattivare le configurazioni di timeout), potresti non vedere sempre lo stesso numero di tentativi. I valori casuali del tremolio per il ritardo RPC rendono difficile prevedere quando la richiesta viene effettivamente inviata.
L'RPC ha restituito un errore prima che venisse raggiunto il valore del timeout totale.
L'algoritmo per i nuovi tentativi calcola il valore del ritardo per i nuovi tentativi con tremolio durante ogni tentativo. Il ritardo per i nuovi tentativi calcolato verrà pianificato per l'esecuzione in futuro (ovvero currentTime() + jitteredRetryDelay). Se l'ora del tentativo pianificato supera il timeout totale, non verrà eseguito l'ultimo tentativo.
Ho configurato impostazioni personalizzate e riscontro problemi di quota.
Potresti aver configurato RetrySettings in modo troppo aggressivo. I valori predefiniti per i nuovi tentativi vengono scelti dal team che gestisce il servizio.
Valuta la possibilità di aumentare il ritardo per i nuovi tentativi (ritardo iniziale per i nuovi tentativi e moltiplicatore di ritardo) in modo che i tentativi siano più distanziati e meno frequenti. Tieni presente che questo può comportare una risposta più lenta.
Il tuo caso d'uso potrebbe richiedere una risposta più rapida o tentativi più frequenti, o entrambi. In questo caso, prova ad aumentare i limiti di quota.