翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
バックオフパターンで再試行
Intent
バックオフによる再試行パターンでは、一時的なエラーが原因で失敗した操作を透過的に再試行することで、アプリケーションの安定性が向上します。
モチベーション
分散型アーキテクチャでは、一時的なエラーは、サービスの調整、ネットワーク接続の一時的な喪失、または一時的なサービスの利用不能が原因である可能性があります。これらの一時的なエラーが原因で失敗した操作を自動的に再試行することで、ユーザーエクスペリエンスとアプリケーションの回復力が向上します。ただし、頻繁に再試行すると、ネットワーク帯域幅が過負荷になり、競合が発生する可能性があります。指数バックオフとは、指定した回数だけ待機時間を増やして操作を再試行する手法です。
適用性
次の場合は、バックオフによる再試行パターンを使用してください。
-
サービスでは、過負荷を防ぐためにリクエストを頻繁に調整しているため、429 リクエストが多すぎます呼び出しプロセスの例外。
-
ネットワークは分散型アーキテクチャでは目に見えない存在であり、一時的なネットワークの問題によって障害が発生します。
-
呼び出されているサービスが一時的に利用できなくなり、障害が発生しています。このパターンを使用してバックオフタイムアウトを導入しない限り、頻繁に再試行するとサービスが低下する可能性があります。
問題と考慮事項
-
イデムポテンス: メソッドへの複数の呼び出しがシステム状態に対する 1 回の呼び出しと同じ効果をもたらす場合、その操作は無能と見なされます。バックオフ付きの再試行パターンを使用する場合、操作は無駄になるはずです。そうしないと、部分的な更新によってシステム状態が壊れる可能性があります。
-
ネットワーク帯域幅: ネットワーク帯域幅を占有する再試行回数が多すぎると、サービスのパフォーマンスが低下し、応答時間が遅くなる可能性があります。
-
フェイルファストシナリオ: 非一時的なエラーの場合、障害の原因を特定できれば、サーキットブレーカーパターンを使用して迅速に障害が発生した方が効率的です。
-
バックオフ率: 指数関数的バックオフを導入すると、サービスのタイムアウトに影響が及び、エンドユーザーの待ち時間が長くなる可能性があります。
実装
高レベルのアーキテクチャ
次の図は、正常に応答が返されるまで、サービス A がサービス B への呼び出しを再試行する方法を示しています。サービス B が数回試行しても成功応答を返さない場合、サービス A は再試行を中止して、呼び出し元に失敗を返すことができます。
を使用した実装AWSサービス
次の図は、カスタマーサポートプラットフォームでのチケット処理ワークフローを示しています。不満を抱いている顧客からのチケットは、チケットの優先度を自動的に上げることによって迅速に処理されます。ザ・Ticket info
Lambda 関数はチケットの詳細を抽出し、Get sentiment
ラムダ関数。ザ・Get sentiment
Lambda 関数は、説明をに渡して顧客の感情をチェックします。アマゾン・コンプリエンド
への電話の場合Get sentiment
Lambda 関数が失敗すると、ワークフローは操作を 3 回再試行します。AWS Step Functionsバックオフ値を設定できるようにすることで、指数関数的バックオフが可能になります。
この例では、1.5 秒の増加倍率で最大 3 回の再試行が設定されています。最初の再試行が 3 秒後に行われた場合、2 回目の再試行は 3 x 1.5 秒 = 4.5 秒後に、3 回目の再試行は 4.5 x 1.5 秒 = 6.75 秒後に行われます。3 回目の再試行が失敗した場合、ワークフローは失敗します。バックオフロジックにはカスタムコードは必要ありません。次の方法で設定として提供されます。AWS Step Functions。
サンプルコード
次のコードは、バックオフパターンによる再試行の実装を示しています。
public async Task DoRetriesWithBackOff() { int retries = 0; bool retry; do { //Sample object for sending parameters var parameterObj = new InputParameter { SimulateTimeout = "false" }; var content = new StringContent(JsonConvert.SerializeObject(parameterObj), System.Text.Encoding.UTF8, "application/json"); var waitInMilliseconds = Convert.ToInt32((Math.Pow(2, retries) - 1) * 100); System.Threading.Thread.Sleep(waitInMilliseconds); var response = await _client.PostAsync(_baseURL, content); switch (response.StatusCode) { //Success case HttpStatusCode.OK: retry = false; Console.WriteLine(response.Content.ReadAsStringAsync().Result); break; //Throttling, timeouts case HttpStatusCode.TooManyRequests: case HttpStatusCode.GatewayTimeout: retry = true; break; //Some other error occured, so stop calling the API default: retry = false; break; } retries++; } while (retry && retries < MAX_RETRIES); }
GitHub倉庫
このパターンのサンプルアーキテクチャの完全な実装については、を参照してください。GitHubリポジトリhttps://github.com/aws-samples/retry-with-backoff
関連情報
-
タイムアウト、リトライ、ジッターを伴うバックオフ
(アマゾンビルダーズライブラリー)