Configura i nuovi tentativi lato client

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:

  1. Retry Status Code: insieme di codici di stato su cui riprovare.
  2. 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:

I limiti RPC totali (un'operazione) sono controllati dalle seguenti impostazioni:

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:

  1. Crea la classe RetrySettings con le tue configurazioni personalizzate:

    RetrySettings customRetrySettings =
      RetrySettings.newBuilder()
        // ... Retry Configurations
        .build();
    RetrySettings customRetrySettings2 =
      RetrySettings.newBuilder()
        // ... Retry Configurations
        .build();
    
  2. Crea StubSettings.Builder per 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 ExportAssets di AssetServiceClient. Configura la RPC ExportAssets in modo che utilizzi le impostazioni di riprova configurate in customRetrySettings e imposta i codici che possono essere riprovati su DEADLINE_EXCEEDED.

  3. Crea le impostazioni per il cliente come assetSettings: java AssetServiceSettings assetSettings = AssetServiceSettings.create(assetStubSettingsBuilder.build()); 4.Crea il cliente con le impostazioni come assetClient. 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.