クライアントサイドの再試行を構成する

Java 用 Cloud クライアント ライブラリは、再試行を使用して予期しない一時的な障害(サーバーが一時的に使用できない状態)を処理します。複数回試行すると、サーバーから正常なレスポンスが返されることがあります。

デフォルトの再試行値は、クラウド サービスを運用するチームによって選択されます。これらの再試行値は RPC ごとに構成されます。サービスは、RPC のサブセットに対してのみ再試行を有効にできます。サービスの各 RPC が異なる方法で構成されている可能性があります。

再試行パラメータ

クライアント ライブラリには、構成する再試行パラメータが 2 種類あります。

  1. 再試行ステータス コード: 再試行するステータス コードのセット。
  2. 再試行タイムアウトまたは試行上限: 上限を定義する構成可能な RetrySettings

デフォルトの RPC 再試行構成の場所

デフォルトの再試行構成は、生成された {Client}StubSettings ファイルで定義されます。Java-Asset v3.64.0 の ExportAssets RPC を例にすると、デフォルトの再試行構成は次の場所で定義されています。

  • 再試行ステータス コード: AssetServiceStubSettings.java ファイルで構成されます。例:

    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();
    
  • 再試行パラメータ: AssetServiceStubSettings.java ファイルで構成されます。例:

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

両方の構成が AssetServiceStubSettings.java ファイルの RPC にマッピングされます。例:

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

クライアント ライブラリの再試行のコンセプト

再試行を有効にすると、RPC は成功した呼び出しを実現するために複数回試行できます。呼び出しが成功すると、サーバーから OK ステータス コード(gRPC から)または 2xx ステータス コード(HttpJson から)が返されます。

試行とオペレーション

次の RetrySettings 構成では、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();

RPC 試行は個々の試行であり、RPC オペレーションはすべての試行の集合です。1 回の RPC 呼び出しには、1 つのオペレーションで 1 回以上の試行が行われます。

個々の RPC の上限(試行)は、次の設定によって制御されます。

合計 RPC 境界(オペレーション)は、次の設定によって制御されます。

RPC が再試行されるとき

次の両方のシナリオが発生すると、RPC が再試行されます。

  • ライブラリが成功以外のステータス コードを受信し、ステータス コードに再試行可能のマークが付けられます。
  • RPC 呼び出しが個々の RPC の上限を超えているが、RPC の合計上限内である。

1 つのシナリオのみが true の場合、またはどちらのシナリオも true でない場合、RPC は再試行されません。

たとえば、合計タイムアウトは超過していないが、最新の試行で再試行できないステータス コードが返された場合などです。

また、RPC の上限を構成するときに、各試行の上限と RPC の合計上限を構成できます。再試行アルゴリズムにより、個々の試行の境界が RPC 全体の境界内に収まるようになります。

指数バックオフ

指数バックオフは、再試行のたびに遅延を増やしながらリクエストを再試行します。この再試行遅延値は、最大再試行遅延値で上限を設定できます。

たとえば、次の再試行構成では、次の遅延時間が発生する可能性があります。

Initial Retry Delay: 100ms
Retry Delay Multiplier: 2.0
Max Retry Delay: 500ms
  • 試行 1: 遅延 100 ミリ秒
  • 試行 2: 遅延 200 ミリ秒
  • 試行 3: 遅延 400 ミリ秒
  • 試行 4: 遅延 500 ミリ秒
  • ...
  • 試行 X: 500 ミリ秒遅延

ジッター

ジッターは、RPC が呼び出されるタイミングを分散させるためにランダム性を使用して追加される分散です。 Google Cloud クライアント ライブラリは、再試行に対して常にジッターを有効にします。これにより、サーバーに過負荷をかけることなく再試行を分散できます。

ジッターのランダム値は、再試行遅延に基づいて計算されます。再試行アルゴリズムは、各試行の前に [1, RETRY_DELAY] の間のランダムな値を計算します。この計算値は、リクエストがサーバーに送信されるまでの概算の遅延時間です。

次の再試行構成では、ジッターと指数バックオフが使用されます。

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

これにより、次のような遅延が発生する可能性があります。

  • 試行 1: [1, 100] ミリ秒のランダムな値を遅延させる
  • 試行 2: [1, 200] ミリ秒のランダムな値を遅延させる
  • 試行 3: [1, 400] ミリ秒のランダムな値を遅延させる
  • 試行 4: [1, 500] ミリ秒のランダムな値を遅延させる
  • ...
  • 試行 X: [1, 500] ミリ秒のランダムな値を遅延させる

再試行の例

次の例は、再試行構成の動作を示しています。

再試行なし

この例では、再試行を無効にします。

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

または、次の例を使用してこの動作を構成することもできます。

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

次の表に試行を示します。

試行回数 RPC タイムアウト 再試行の遅延 Call Invoked 通話終了
1 5000 ミリ秒 0ms 0ms 5000 ミリ秒

再試行の例

この例では、指定された遅延とタイムアウトで再試行を有効にします。

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

次の表に試行を示します。

試行回数 RPC タイムアウト 再試行の遅延 Call Invoked 通話終了
1 1500 ミリ秒 0ms 0ms 1500 ミリ秒
2(再試行) 3000 ミリ秒 200ms 1700 ミリ秒 4700 ミリ秒
3(再試行が試行されなかった) - 400ms - -

再試行の例: 合計タイムアウトを長くする

この例は最初の再試行の例と似ていますが、合計タイムアウトが長くなっています。これは、追加の再試行と、最後の再試行の RPC タイムアウトの上限を示すためです。

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

次の表に試行を示します。

試行回数 RPC タイムアウト 再試行の遅延 Call Invoked 通話終了
1 1500 ミリ秒 0ms 0ms 1500 ミリ秒
2(再試行) 3000 ミリ秒 200ms 1700 ミリ秒 4700 ミリ秒
3(再試行) 4900 ミリ秒 400ms 5100 ミリ秒 10000ms

3 回目の再試行 RPC タイムアウト値は、合計タイムアウト値によって制限されます。乗数(2.0)を前のタイムアウト値(3,000 ミリ秒)で使用すると、RPC タイムアウトは 6,000 ミリ秒になります。ただし、RPC タイムアウトは合計タイムアウトを超えてはならず、「残り時間」(10000 - 5100 = 4900)に短縮されます。

再試行の例: 上限付き RPC タイムアウト

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

次の表に試行を示します。

試行回数 RPC タイムアウト 再試行の遅延 Call Invoked 通話終了
1 500ms 0ms 0ms 500ms
2(再試行) 1000 ミリ秒 200ms 700ミリ秒 1700 ミリ秒
3(再試行) 1900ms 400ms 2100 ミリ秒 4000 ミリ秒

RPC タイムアウトが合計タイムアウトを超えないように上限が設定されている別の例。

RPC のカスタム再試行パラメータを構成する方法

次の例では、Java-Asset クライアント ライブラリを使用します。

  1. カスタム構成を使用して RetrySettings クラスを作成します。

    RetrySettings customRetrySettings =
      RetrySettings.newBuilder()
        // ... Retry Configurations
        .build();
    RetrySettings customRetrySettings2 =
      RetrySettings.newBuilder()
        // ... Retry Configurations
        .build();
    
  2. クライアントの StubSettings.Builder を作成し、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));
    

    提供されているコード スニペットは、AssetServiceClientExportAssets RPC のカスタム再試行構成を設定しています。ExportAssets RPC が customRetrySettings で構成された再試行設定を使用するように構成し、再試行可能なコードを DEADLINE_EXCEEDED に設定します。

  3. クライアントの設定を assetSettings として作成します。 java AssetServiceSettings assetSettings = AssetServiceSettings.create(assetStubSettingsBuilder.build()); 4. 設定を assetClient としてクライアントを作成します。java try (AssetServiceClient assetClient = AssetServiceClient.create(assetSettings)) { ... }

構成する RPC ごとに手順 2 を繰り返します。次に例を示します。

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

よくある質問

以下に、クライアントの再試行動作に関するよくある質問を示します。

再試行回数は X 回になるはずだったが、Y 回になった。

最大試行回数を明示的に指定しない限り(タイムアウト構成を無効にする場合も同様)、再試行回数が常に同じになるとは限りません。RPC 遅延のジッター ランダム値により、リクエストが実際に送信されるタイミングを予測することが困難になります。

RPC は、合計タイムアウト値に達する前に失敗を返しました。

再試行アルゴリズムは、再試行のたびにジッター付きの再試行遅延値を計算します。計算された再試行遅延は、将来(つまり currentTime() + jitteredRetryDelay)に実行されるようにスケジュールされます。スケジュールされた試行時間が合計タイムアウトを超えると、最後の再試行は行われません。

カスタム設定を構成しましたが、割り当てに関する問題が発生しています。

RetrySettings が過度に実行されるように構成されている可能性があります。デフォルトの再試行値は、サービスを運用するチームによって選択されます。

再試行の間隔を長くして頻度を減らすには、再試行遅延(初期再試行遅延と再試行乗数)を増やすことを検討してください。この場合、レスポンスが遅くなる可能性があります。

ユースケースによっては、より迅速なレスポンスやより頻繁な再試行が必要になることがあります。その場合は、割り当て上限の引き上げを試してください。