リクエストヘッジング

リクエストヘッジングとは何か、およびそれをどのように設定できるかを説明します。

リクエストヘッジング

リクエストヘッジングとは何か、およびそれをどのように設定できるかを説明します。

概要

ヘッジングは、gRPCがサポートする2つの設定可能なリトライポリシーのうちの1つです。ヘッジングを使用すると、gRPCクライアントは同じリクエストの複数のコピーを異なるバックエンドに送信し、最初に受信した応答を使用します。その後、クライアントは保留中のリクエストをキャンセルし、応答をアプリケーションに転送します。

Basic hedging diagram

ユースケース

ヘッジングは、大規模分散システムでテールレイテンシを削減するためのテクニックです。単純な実装ではバックエンドサーバーにかなりの負荷がかかる可能性がありますが、負荷をわずかに増加させるだけで、レイテンシ削減効果のほとんどを得ることが可能です。

テールレイテンシに関する詳細な議論については、Jeff DeanとLuiz André Barrosoによる画期的な論文「The Tail At Scale」を参照してください。

gRPCでのヘッジングの設定

ヘッジングは、gRPCサービス構成を介して、メソッドごとに設定できます。この構成には、次のノブが含まれています。

"hedgingPolicy": {
  "maxAttempts": INTEGER,
  "hedgingDelay": JSON proto3 Duration type,
  "nonFatalStatusCodes": JSON array of grpc status codes (int or string)
}
  • maxAttempts:成功した応答を待つ間、実行中のリクエストの最大数。これは必須フィールドであり、指定する必要があります。指定された値が5より大きい場合、gRPCは5の値を使用します。
  • hedgingDelay:成功した応答を待つ間、クライアントが次のリクエストを送信するまでに経過する必要のある時間量。このフィールドはオプションであり、指定しない場合、maxAttempts数のリクエストがすべて同時に送信されます。
  • nonFatalStatusCodes:オプションのgRPCステータスコードのリスト。ヘッジされたリクエストのいずれかがこのリストに存在しないステータスコードで失敗した場合、すべての保留中のリクエストはキャンセルされ、応答はアプリケーションに返されます。

ヘッジングポリシー

アプリケーションがサービス構成にhedgingPolicy構成を含むRPC呼び出しを行うと、標準のヘッジされていない呼び出しと同様に、元のRPCがすぐに送信されます。成功した応答なしでhedgingDelayが経過した後、2番目のRPCが発行されます。hedgingDelayが再度経過してもどちらのRPCも応答を受信しなかった場合、3番目のRPCが送信され、maxAttemptsまで続きます。gRPC呼び出しのデッドラインは、ヘッジされたリクエストのチェーン全体に適用されます。デッドラインを過ぎると、実行中のRPCやヘッジング構成に関係なく、操作は失敗します。

成功した応答が受信された場合(ヘッジされたリクエストのいずれかへの応答)、すべての保留中のヘッジされたリクエストはキャンセルされ、応答はクライアントアプリケーションレイヤーに返されます。

ヘッジされたリクエストから致命的でないステータスコード(nonFatalStatusCodesフィールドで制御)のエラー応答を受信した場合、次のヘッジされたリクエストはすぐに送信され、ヘッジング遅延がショートカットされます。他のステータスコードを受信した場合、すべての保留中のRPCはキャンセルされ、エラーはクライアントアプリケーションレイヤーに返されます。

ヘッジされたRPCのすべてのインスタンスが失敗した場合、追加のリトライ試行はありません。本質的に、ヘッジングは、失敗が受信される前に元のRPCをリトライしていると見なすことができます。

リトライしないことを指定するサーバーからのプッシュバックがヘッジされたリクエストに応答して受信された場合、その呼び出しに対してこれ以上ヘッジされたリクエストを発行しないでください。

ヘッジされたRPCのレート制限

gRPCは、サーバーの過負荷を防ぐためにヘッジされたRPCをスロットリングする方法を提供します。スロットリングは、サービス構成を使用してRetryThrottlingPolicyメッセージでも構成できます。スロットリング構成には、次のものが含まれます。

"retryThrottling": {
  "maxTokens": 10,
  "tokenRatio": 0.1
}

各サーバー名について、gRPCクライアントは、最初にmax_tokensに設定されるtoken_countを維持します。すべての送信RPC(サービスまたはメソッドの呼び出しにかかわらず)は、token_countを次のように変更します。

  • 失敗したRPCはすべてtoken_count1だけデクリメントします。
  • 成功したRPCはすべてtoken_counttoken_ratioだけインクリメントします。

ヘッジングを使用すると、最初のリクエストは常に送信されますが、後続のヘッジされたリクエストはtoken_countがしきい値(max_tokens / 2と定義)より大きい場合にのみ送信されます。token_countがしきい値以下の場合、ヘッジされたリクエストはブロックされません。代わりにキャンセルされ、すでに送信されたヘッジされたRPCがない場合、失敗はクライアントアプリケーションに返されます。

スロットリングポリシーの失敗としてカウントされるのは、致命的でないステータスコードで失敗したリクエスト、またはリトライしないことを示すプッシュバック応答を受信したリクエストのみです。これにより、サーバーの障害と、フォーマットされていないリクエスト(INVALID_ARGUMENTステータスコードなど)への応答を混同することを避けることができます。

サーバーからのプッシュバック

サーバーは、クライアントへの応答にメタデータを設定することで明示的にプッシュバックできます。プッシュバックがリトライしないように指示している場合、これ以上ヘッジされたリクエストは送信されません。プッシュバックが指定された遅延後にリトライするように指示している場合、次のヘッジされたリクエスト(存在する場合)は、指定された遅延が経過した後に発行されます。

サーバーのプッシュバックは、メタデータキーgrpc-retry-pushback-msを使用して指定されます。値は、次のヘッジされたリクエストを送信する前に待機する必要があるミリ秒数を示す、ASCIIエンコードされた符号付き32ビット整数であり、不要な先頭ゼロはありません。プッシュバックの値が負または解析不可能な場合、サーバーがクライアントにまったくリトライしないように要求していると見なされます。

リソース

言語サポート

言語
JavaJavaの例
C++まだ利用できません
Goまだサポートされていません
最終更新日:2023年10月3日:Add a guide for request hedging (#1199) (d357308)