Clientseitige Wiederholungen konfigurieren

In Cloud-Clientbibliotheken für Java werden Wiederholungsversuche verwendet, um unerwartete, vorübergehende Fehler zu beheben (d. h., der Server ist vorübergehend nicht verfügbar). Mehrere Versuche können zu einer erfolgreichen Antwort des Servers führen.

Die Standardwerte für Wiederholungen werden vom Team ausgewählt, das den Cloud-Dienst betreibt. Diese Werte für Wiederholungsversuche werden pro RPC konfiguriert. Ein Dienst kann Wiederholungen nur für eine Teilmenge von RPCs aktivieren. Es ist möglich, dass jeder RPC für einen Dienst unterschiedlich konfiguriert ist.

Wiederholungsparameter

In Clientbibliotheken gibt es zwei Arten von Wiederholungsparametern, die konfiguriert werden können:

  1. Statuscode für Wiederholung:Eine Reihe von Statuscodes, bei denen die Anfrage wiederholt werden soll.
  2. Zeitüberschreitung für Wiederholungsversuche oder Grenzwerte für Versuche:Konfigurierbare RetrySettings zum Definieren der Grenzwerte.

Standardspeicherort der RPC-Wiederholungskonfiguration

Die Standardkonfigurationen für Wiederholungsversuche sind in der generierten Datei {Client}StubSettings definiert. Die Standardkonfigurationen für Wiederholungsversuche sind beispielsweise in der Java-Asset-Version 3.64.0 für den RPC „ExportAssets“ an den folgenden Stellen definiert:

  • Wiederholungsstatuscodes:In der Datei AssetServiceStubSettings.java konfiguriert. Beispiel:

    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();
    
  • Wiederholungsparameter:In der Datei AssetServiceStubSettings.java konfiguriert. Beispiel:

    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();
    

Beide Konfigurationen werden in der Datei AssetServiceStubSettings.java dem RPC zugeordnet. Beispiel:

builder
  .exportAssetsSettings()
  .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("no_retry_0_codes"))
  .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("no_retry_0_params"));

Wiederholungskonzepte für Clientbibliotheken

Wenn Sie Wiederholungen aktivieren, kann ein RPC mehrere Versuche unternehmen, um einen erfolgreichen Aufruf zu erzielen. Ein erfolgreicher Aufruf ist eine Antwort von einem Server, der einen OK-Statuscode (von gRPC) oder einen 2xx-Statuscode (von HttpJson) zurückgibt.

Versuch im Vergleich zum Vorgang

Die folgende RetrySettings-Konfiguration ändert die Einstellungen für Wiederholungsversuche für einen RPC-Versuch und einen Vorgang:

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();

Ein RPC-Versuch ist der einzelne Versuch, der unternommen wird, und ein RPC-Vorgang ist eine Sammlung aller Versuche. Ein einzelner RPC-Aufruf hat einen oder mehrere Versuche in einem einzelnen Vorgang.

Einzelne RPC-Grenzen (ein Versuch) werden durch die folgenden Einstellungen gesteuert:

Die Gesamtzahl der RPC-Aufrufe (ein Vorgang) wird durch die folgenden Einstellungen gesteuert:

Wenn ein RPC wiederholt wird

Ein RPC wird wiederholt, wenn beide der folgenden Szenarien eintreten:

  • Die Bibliothek empfängt einen nicht erfolgreichen Statuscode und der Statuscode wird als wiederholbar markiert.
  • Ein RPC-Aufruf überschreitet die individuellen RPC-Grenzwerte, liegt aber noch innerhalb der Gesamt-RPC-Grenzwerte.

Wenn nur ein Szenario zutrifft oder keines der beiden Szenarien zutrifft, wird der RPC nicht noch einmal versucht.

Das kann z. B. der Fall sein, wenn das Gesamttimeout nicht überschritten wurde, der letzte Versuch aber einen Statuscode zurückgibt, der nicht wiederholt werden kann.

Außerdem können Sie beim Konfigurieren der RPC-Grenzwerte die Grenzwerte für jeden Versuch sowie die Grenzwerte für den gesamten RPC konfigurieren. Der Wiederholungsalgorithmus sorgt dafür, dass die Grenzen eines einzelnen Versuchs innerhalb der Grenzen des gesamten RPC liegen.

Exponentielle Backoffs

Beim exponentiellen Backoff werden Anfragen mit einer zunehmenden Verzögerung zwischen den einzelnen Wiederholungsversuchen wiederholt. Dieser Wert für die Wiederholungsverzögerung kann durch einen maximalen Wert für die Wiederholungsverzögerung begrenzt werden.

Die folgenden Konfigurationen für Wiederholungsversuche können beispielsweise zu den folgenden Verzögerungszeiten führen:

Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
  • Versuch 1: Verzögerung von 100 ms
  • Versuch 2: Verzögerung von 200 ms
  • Versuch 3: Verzögerung von 400 ms
  • Versuch 4: Verzögerung von 500 ms
  • Versuch X: Verzögerung von 500 ms

Jitter

Jitter ist eine zusätzliche Varianz, die durch Zufälligkeit hinzugefügt wird, um die Aufrufe der RPCs zu verteilen. Google Cloud Clientbibliotheken aktivieren Jitter immer für Wiederholungsversuche. So werden die Wiederholungsversuche verteilt, ohne den Server zu überlasten.

Der zufällige Jitter-Wert wird auf Grundlage der Verzögerung für den Wiederholungsversuch berechnet. Vor jedem Versuch berechnet der Wiederholungsalgorithmus einen zufälligen Wert zwischen [1, RETRY_DELAY]. Dieser berechnete Wert ist die ungefähre Verzögerung, bevor die Anfrage an den Server gesendet wird.

Bei den folgenden Konfigurationen für Wiederholungsversuche werden Jitter und exponentieller Backoff verwendet.

Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms

Das kann zu folgenden Verzögerungszeiten führen:

  • 1. Versuch: Verzögern Sie einen zufälligen Wert zwischen [1, 100] ms.
  • 2. Versuch: Verzögern Sie einen zufälligen Wert zwischen [1, 200] ms.
  • 3. Versuch: Verzögern Sie einen zufälligen Wert zwischen [1, 400] ms.
  • 4. Versuch: Verzögern Sie einen zufälligen Wert zwischen [1, 500] ms.
  • Versuch X: Verzögere einen zufälligen Wert zwischen [1, 500] ms

Beispiele für Wiederholungen

Die folgenden Beispiele zeigen das Verhalten einiger Konfigurationen für Wiederholungsversuche.

Kein Wiederholungsversuch

In diesem Beispiel werden Wiederholungsversuche deaktiviert.

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();

Alternativ kann dieses Verhalten mit diesem Beispiel konfiguriert werden:

RetrySettings defaultNoRetrySettings =
    RetrySettings.newBuilder()
    .setLogicalTimeoutDuration(Duration.ofMillis(5000L))
    .build();

In der folgenden Tabelle sind die Versuche aufgeführt:

Versuchsnummer RPC-Zeitlimit Verzögerung für Wiederholung Anruf aufgerufen Anruf beendet
1 5000 ms 0 ms 0 ms 5000 ms

Beispiel für „Wiederholen“

In diesem Beispiel werden Wiederholungen mit angegebenen Verzögerungen und Zeitlimits aktiviert.

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();

In der folgenden Tabelle sind die Versuche aufgeführt:

Versuchsnummer RPC-Zeitlimit Verzögerung für Wiederholung Anruf aufgerufen Anruf beendet
1 1500 ms 0 ms 0 ms 1500 ms
2 (Wiederholen) 3.000 ms 200 ms 1700 ms 4700 ms
3 (Wiederholung nicht versucht) - 400 ms - -

Beispiel für Wiederholung: längere Gesamtauszeit

Dieses Beispiel ähnelt dem ersten Beispiel für Wiederholungsversuche, hat aber eine längere Gesamt-Zeitüberschreitung, um einen zusätzlichen Wiederholungsversuch und die maximale RPC-Zeitüberschreitung für den letzten Wiederholungsversuch zu veranschaulichen.

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();

In der folgenden Tabelle sind die Versuche aufgeführt:

Versuchsnummer RPC-Zeitlimit Verzögerung für Wiederholung Anruf aufgerufen Anruf beendet
1 1500 ms 0 ms 0 ms 1500 ms
2 (Wiederholen) 3.000 ms 200 ms 1700 ms 4700 ms
3 (Wiederholen) 4.900 ms 400 ms 5.100 ms 10.000 ms

Der RPC-Zeitüberschreitungswert für den dritten Wiederholungsversuch ist aufgrund des Gesamtwerts für das Zeitlimit begrenzt. Wenn Sie den Multiplikator (2,0) mit dem vorherigen Zeitüberschreitungswert (3.000 ms) verwenden, ergibt sich eine RPC-Zeitüberschreitung von 6.000 ms. Die RPC-Zeitüberschreitung darf jedoch nicht die Gesamtzeitüberschreitung überschreiten und wird auf die verbleibende Zeit reduziert (10.000 – 5.100 = 4.900).

Beispiel für Wiederholung: Begrenztes RPC-Zeitlimit

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();

In der folgenden Tabelle sind die Versuche aufgeführt:

Versuchsnummer RPC-Zeitlimit Verzögerung für Wiederholung Anruf aufgerufen Anruf beendet
1 500 ms 0 ms 0 ms 500 ms
2 (Wiederholen) 1000 ms 200 ms 700 ms 1700 ms
3 (Wiederholen) 1900 ms 400 ms 2100 ms 4000 ms

Ein weiteres Beispiel, bei dem das RPC-Zeitlimit begrenzt wird, damit es das Gesamttimeout nicht überschreitet.

Benutzerdefinierte Wiederholungsparameter für einen RPC konfigurieren

Im folgenden Beispiel wird die Java-Asset-Clientbibliothek verwendet:

  1. Erstellen Sie die RetrySettings-Klasse mit Ihren benutzerdefinierten Konfigurationen:

    RetrySettings customRetrySettings =
      RetrySettings.newBuilder()
        // ... Retry Configurations
        .build();
    RetrySettings customRetrySettings2 =
      RetrySettings.newBuilder()
        // ... Retry Configurations
        .build();
    
  2. Erstellen Sie die StubSettings.Builder für Ihren Client und konfigurieren Sie sie für den 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));
    

    Mit dem bereitgestellten Code-Snippet werden benutzerdefinierte Konfigurationen für Wiederholungsversuche für den ExportAssets-RPC von AssetServiceClient festgelegt. Damit wird der ExportAssets-RPC so konfiguriert, dass die in customRetrySettings konfigurierten Wiederholungseinstellungen verwendet werden, und die Codes, die wiederholt werden können, werden auf DEADLINE_EXCEEDED festgelegt.

  3. Erstellen Sie die Einstellungen für den Client als assetSettings: java AssetServiceSettings assetSettings = AssetServiceSettings.create(assetStubSettingsBuilder.build()); 4.Erstellen Sie den Client mit den Einstellungen als assetClient. java try (AssetServiceClient assetClient = AssetServiceClient.create(assetSettings)) { ... }

Wiederholen Sie Schritt 2 für jeden RPC, den Sie konfigurieren möchten. Beispiel:

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));

FAQ

Im Folgenden finden Sie häufig gestellte Fragen zum Wiederholungsverhalten von Clients.

Ich habe X Wiederholungsversuche erwartet, aber es wurden Y Versuche unternommen.

Sofern Sie die maximale Anzahl von Versuchen nicht explizit angeben (und die Timeout-Konfigurationen deaktivieren), wird die Anzahl der Wiederholungsversuche möglicherweise nicht immer gleich sein. Durch die zufälligen Jitter-Werte für die RPC-Verzögerung ist es schwierig, vorherzusagen, wann die Anfrage tatsächlich gesendet wird.

Der RPC hat einen Fehler zurückgegeben, bevor der Wert für „Total Timeout“ erreicht wurde.

Der Algorithmus für Wiederholungsversuche berechnet den Wert für die verzögerte Wiederholung bei jedem Wiederholungsversuch. Die berechnete Verzögerung für den Wiederholungsversuch wird für die Zukunft geplant (d. h. currentTime() + jitteredRetryDelay). Wenn die geplante Zeit für den Versuch das gesamte Zeitlimit überschreitet, wird der letzte Wiederholungsversuch nicht ausgeführt.

Ich habe benutzerdefinierte Einstellungen konfiguriert und es treten Kontingentprobleme auf.

Möglicherweise haben Sie RetrySettings zu aggressiv konfiguriert. Die Standardwerte für Wiederholungsversuche werden vom Team ausgewählt, das den Dienst betreibt.

Erhöhen Sie die Verzögerung für Wiederholungsversuche (anfängliche Verzögerung für Wiederholungsversuche und Multiplikator für Wiederholungsversuche), damit die Wiederholungsversuche in größeren Abständen und weniger häufig erfolgen. Dadurch kann es zu einer langsameren Reaktion kommen.

Je nach Anwendungsfall kann eine schnellere Antwort oder häufigere Wiederholungsversuche oder beides erforderlich sein. Versuchen Sie in diesem Fall, die Kontingentlimits zu erhöhen.