リトライ
gRPCは失敗によるストレスを軽減します!OpenCensusおよびOpenTelemetryサポートにより、きめ細かなリトライ制御と詳細な洞察を提供します。
リトライ
概要
リトライは、サービスをより信頼性の高いものにするための重要なパターンです。失敗した操作を再試行することにより、アプリケーションはネットワークやサーバーのグリッチなどの一時的な問題を克服できます。これは、現代のクラウドアプリケーションが必然的に発生する一時的な障害を処理するために不可欠です。
ベストプラクティスとして、アプリケーションはリトライに適した失敗した操作を理解し、リトライ遅延のための指数関数的バックオフパラメータを定義し、リトライ回数を決定し、リトライメトリクスを監視する必要があります。
gRPCクライアントのリトライはどのように機能するか
gRPCの組み込みリトライロジックは、リトライの可能性のために呼び出しの履歴を保存し、RPCイベントを監視します。リトライポリシーが設定されていなくても、gRPCは透過的なリトライ(後述)を実行する必要がある場合に備えて、呼び出しの履歴を保存します。'リトライ'とは、失敗した呼び出しを新しい呼び出しに置き換えて、その新しく作成された呼び出しで呼び出しの履歴を再生することを意味します。
特定の基準(RPCがリトライポリシーのリトライ可能ステータスコードと一致する失敗ステータスコードで閉じ、リトライ試行回数制限内にある)が満たされると、gRPCは指数関数的バックオフ遅延の後に新しいリトライストリームを作成します。
gRPCは、リトライのサーバースロットリングやサーバープッシュバックなどの他の機能もサポートしています。詳細については、クライアントサイドリトライのgRFCを参照してください。
レスポンスヘッダーが受信されると、RPCはコミットされます。それ以上のリトライは試行されず、gRPCはRPCをアプリケーションに引き渡します。
以下のグラフは、gRPCリトライ内部のアーキテクチャ概要を示しています。
sequenceDiagram
Application ->> gRPC Client: Configure retry policy. <br> Send request to dns:///my-service
gRPC Client ->> gRPC Client: Save message
gRPC Client ->> Server: Create initial attempt
Server -->> gRPC Client : RPC closed with error
gRPC Client ->> Server: Create retry attempt 1
Server -->> gRPC Client: Successful
gRPC Client ->> Application: No more retry. Proceed.
リトライ設定
リトライはデフォルトで有効になっていますが、デフォルトのリトライポリシーはありません。リトライポリシーがない場合、gRPCはほとんどの場合RPCを安全にリトライできません。低レベルの競合によって失敗したRPCのみがリトライされ、gRPCがRPCがサーバーによって処理されていないと確信している場合にのみリトライされます。これは「透過的リトライ」として知られています。リトライポリシーを構成することで、gRPCがより多くの状況で、より積極的にRPCをリトライできるようになります。チャネルを作成する際にリトライを完全に無効にすることもできます。これにより、透過的リトライおよび設定されたリトライポリシーが無効になります。
透過的リトライ
障害はさまざまな段階で発生する可能性があります。明示的なリトライポリシーがない場合でも、gRPCは透過的なリトライを実行することがあります。これらのリトライの範囲は、障害が発生したタイミングによって異なります。
- RPCがクライアントからまったく送信されない場合、gRPCは無制限の透過的リトライを実行する可能性があります。
- RPCがgRPCサーバーライブラリに到達したが、サーバーアプリケーションロジックにはまったく見られていない場合、gRPCは単一の透過的リトライを実行します。このタイプのリトライはネットワークに負荷をかけるため、注意してください。
gRPCがサポートする主要なステップと構成に焦点を当てることで、アプリケーションのリトライ機能を最適化できます。
- 最大リトライ試行回数
- 指数関数的バックオフ
- リトライ可能ステータスコードのセット
リトライは、gRPCサービス構成を介して、メソッドごとに設定可能です。構成には以下のノブが含まれます。
"retryPolicy": {
"maxAttempts": 4,
"initialBackoff": "0.1s",
"maxBackoff": "1s",
"backoffMultiplier": 2,
"retryableStatusCodes": [
"UNAVAILABLE"
]
}
サーバーへの同時アクセスを避けるため、バックオフ遅延にプラスマイナス20%のジッターが適用されます。上記の構成例では、initialBackoffが100msに設定されているため、最初の試行後の実際のバックオフ遅延は、[80ms、120ms]の範囲内のランダムな時間になります。
gRPCは、リトライによるサーバー過負荷を防ぐためのスロットリング制限をサポートしています。以下は、リトライスロットリング構成の例です。
"retryThrottling": {
"maxTokens": 10,
"tokenRatio": 0.1
}
各サーバーについて、gRPCクライアントはtoken_count(初期値はmaxTokens)を追跡します。失敗したRPCはカウントを1減らし、成功したRPCはtokenRatioだけカウントを増やします。token_countがmaxTokensの半分を下回った場合、カウントが回復するまでリトライは一時停止されます。
さらに、ヘッジングはリトライの補完的な機能であり、同様に設定できます。詳細については、ヘッジングガイドを参照してください。
リトライのオブザーバビリティ
gRPCは、リトライ機能が有効になっている場合にOpenCensusおよびOpenTelemetryメトリクスを公開することをサポートしています。以下は、利用可能なOpenTelemetryリトライ試行統計の例です。
grpc.client.attempt.startedgrpc.client.attempt.durationgrpc.client.attempt.sent_total_compressed_message_sizegrpc.client.attempt.rcvd_total_compressed_message_size
各呼び出しレベルでのメトリクス
grpc.client.call.duration
およびサーバーサイドメトリクス
grpc.server.call.startedgrpc.server.call.sent_total_compressed_message_sizegrpc.server.call.rcvd_total_compressed_message_sizegrpc.server.call.duration
詳細なメトリクスとトレーシング情報、および構成手順については、OtelメトリクスのgRFC、リトライステータスのgRFCを参照してください。
言語ガイドと例
| 言語 | 例 | ドキュメント |
|---|---|---|
| C++ | ||
| Go | Go 例 | |
| Java | Java 例 | Java ドキュメント |
| Python | Python 例 |