リクエストヘッジング

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

リクエストヘッジング

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

概要

ヘッジングは、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が発行されます。どちらのRPCもhedgingDelayが再び経過してもレスポンスを受信していない場合、3番目のRPCが送信されるなど、maxAttemptsまで続きます。gRPC呼び出しのデッドラインは、ヘッジされたリクエストの entire chain に適用されます。デッドラインが過ぎると、実行中のRPCに関係なく、ヘッジング設定に関係なく、操作は失敗します。

成功したレスポンスが受信されると(ヘッジされたリクエストのいずれかに対するレスポンスとして)、未処理のヘッジされたリクエストはすべてキャンセルされ、レスポンスがクライアントアプリケーションレイヤーに返されます。

非致命的なステータスコード(nonFatalStatusCodesフィールドで制御)のエラーレスポンスがヘッジされたリクエストから受信された場合、次のヘッジされたリクエストがすぐに送信され、ヘッジの遅延が短縮されます。その他のステータスコードが受信された場合、未処理のRPCはすべてキャンセルされ、エラーがクライアントアプリケーションレイヤーに返されます。

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

リトライしないことを指定するサーバーからのプッシュバックが、ヘッジされたリクエストへのレスポンスとして受信された場合、その呼び出しに対してそれ以上のヘッジされたリクエストは発行されません。

ヘッジされたRPCのスロットリング

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

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

各サーバー名に対して、gRPCクライアントはtoken_countを保持し、これは最初にmax_tokensに設定されます。発信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まだサポートされていません