翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
サーキットブレーカーパターン
Intent
サーキットブレーカーパターンは、呼び出しが以前に繰り返しタイムアウトまたは失敗の原因になったときに、呼び出し元サービスが別のサービス (呼び出し元 ) への呼び出しを再試行するのを防ぐことができます。このパターンは、呼び出し元サービスが再び機能するタイミングを検出するために使用されます。
導入する理由
複数のマイクロサービスが連携してリクエストを処理する場合、1 つ以上のサービスが使用できなくなったり、レイテンシーが長くなったりする可能性があります。複雑なアプリケーションがマイクロサービスを使用する場合、1 つのマイクロサービスが停止すると、アプリケーションの障害が発生する可能性があります。マイクロサービスはリモートプロシージャ呼び出しを介して通信し、ネットワーク接続に一時的なエラーが発生して障害が発生する可能性があります。(一時的なエラーは、バックオフパターンを使用した再試行を使用して処理できます)。同期実行中にタイムアウトや障害がカスケードすると、ユーザーエクスペリエンスが低下する可能性があります。
ただし、状況によっては、障害の解決に時間がかかることがあります。例えば、発信者サービスがダウンしている場合や、データベースの競合によってタイムアウトが発生した場合などです。このような場合、呼び出し元のサービスが呼び出しを繰り返し再試行すると、これらの再試行によってネットワークの競合が発生し、データベーススレッドプールが消費される可能性があります。さらに、複数のユーザーがアプリケーションを繰り返し再試行すると、問題が悪化し、アプリケーション全体でパフォーマンスが低下する可能性があります。
サーキットブレーカーパターンは、マイケル・ナイガードによる本「リリース・イ」(2018 年ナイガード) で人気がありました。この設計パターンにより、以前にタイムアウトや障害が繰り返し発生したサービス呼び出しを呼び出し元サービスが再試行するのを防ぐことができます。また、発信者サービスが再び機能するタイミングを検出することもできます。
サーキットブレーカーオブジェクトは、回路に異常がある場合に現在の を自動的に中断する電気サーキットブレーカーのように機能します。障害発生時に、回路ブレーカーが現在のフローをシャットダウンまたは作動させます。同様に、サーキットブレーカーオブジェクトは発信者と受信者サービスの間で動作し、発信者が利用できない場合は作動します。
分散コンピューティングのフォールカシー
ネットワークの停止中、アプリケーションは応答を無期限に待機し、アプリケーションリソースを継続的に消費する可能性があります。ネットワークが使用可能になったときにオペレーションを再試行しないと、アプリケーションのパフォーマンスが低下する可能性があります。ネットワークの問題により、データベースまたは外部サービスへの API コールがタイムアウトした場合、サーキットブレーカーなしで呼び出しを繰り返すと、コストとパフォーマンスに影響する可能性があります。
適用対象
このパターンは次の場合に使用します。
-
発信者サービスは、失敗する可能性が最も高い呼び出しを行います。
-
発信者サービスが示すレイテンシーが高い場合 (例えば、データベース接続が遅い場合)、発信者サービスにタイムアウトが発生します。
-
発信者サービスは同期呼び出しを行いますが、発信者サービスは利用できないか、レイテンシーが長くなります。
問題点と考慮事項
-
サービスに依存しない実装: コードの肥大化を防ぐため、マイクロサービスに依存しない API 主導の方法でサーキットブレーカーオブジェクトを実装することをお勧めします。
-
発信者による回路閉鎖: 発信者がパフォーマンスの問題または障害から回復すると、回路のステータスを に更新できます
CLOSED
。これはサーキットブレーカーパターンの拡張であり、目標復旧時間 (RTO) で必要な場合に実装できます。 -
マルチスレッド呼び出し: 有効期限タイムアウト値は、サービスの可用性を確認するために呼び出しが再度ルーティングされるまでに回路が作動する期間として定義されます。複数のスレッドで被着信者サービスが呼び出されると、最初に失敗した呼び出しによって有効期限のタイムアウト値が定義されます。実装では、後続の呼び出しによって有効期限が無限に移動しないようにする必要があります。
-
回路を強制的に開いたり閉じたりする: システム管理者は、回路を開いたり閉じたりできる必要があります。これは、データベーステーブルの有効期限タイムアウト値を更新することで実行できます。
-
オブザーバビリティ: アプリケーションでは、サーキットブレーカーが開いているときに失敗する呼び出しを識別するためのログ記録を設定する必要があります。
実装
高レベルのアーキテクチャ
次の例では、発信者が注文サービスで、発信者が支払いサービスです。
障害がない場合、次の図に示すように、注文サービスはすべての呼び出しをサーキットブレーカーによって支払いサービスにルーティングします。
![障害のないサーキットブレーカーパターン。](images/circuit-breaker-1.png)
支払いサービスがタイムアウトすると、サーキットブレーカーはタイムアウトを検出し、障害を追跡できます。
![支払いサービスに障害が発生したサーキットブレーカー。](images/circuit-breaker-2.png)
タイムアウトが指定されたしきい値を超えると、アプリケーションは回路を開きます。回路が開いている場合、サーキットブレーカーオブジェクトは呼び出しを支払いサービスにルーティングしません。注文サービスが支払いサービスを呼び出すと、即時の失敗が返されます。
![サーキットブレーカーは支払いサービスへのルーティングを停止します。](images/circuit-breaker-3.png)
サーキットブレーカーオブジェクトは、支払いサービスへの呼び出しが成功したかどうかを定期的に確認しようとします。
![サーキットブレーカーは定期的に支払いサービスを再試行します。](images/circuit-breaker-4.png)
支払いサービスの呼び出しが成功すると、回路は閉じられ、それ以降のすべての呼び出しは支払いサービスに再度ルーティングされます。
![有効な支払いサービスを備えたサーキットブレーカー。](images/circuit-breaker-5.png)
AWS のサービスを使用した実装
サンプルソリューションでは、 の Express ワークフローAWS Step Functions
このソリューションでは、Amazon DynamoDB
サービスが別のサービスを呼び出す場合、呼び出し元サービスの名前でワークフローを開始します。ワークフローは DynamoDB テーブルからサーキットブレーカーのステータスを取得します。DynamoDBCircuitStatus
テーブルには、現在パフォーマンスが低下しているサービスが保存されます。に発信者の期限切れでないレコードCircuitStatus
が含まれている場合、回路は開いています。Step Functions ワークフローは即時障害を返し、 FAIL
状態で終了します。
CircuitStatus
テーブルに発信者のレコードが含まれていない場合、または期限切れのレコードが含まれている場合、サービスは動作します。ステートマシン定義の ExecuteLambda
ステップは、パラメータ値を介して送信される Lambda 関数を呼び出します。呼び出しが成功すると、Step Functions ワークフローは SUCCESS
状態で終了します。
![AWS Step Functions および DynamoDB を使用したサーキットブレーカーの実装。](images/circuit-breaker-6.png)
サービスコールが失敗するか、タイムアウトが発生した場合、アプリケーションは定義された回数だけエクスポネンシャルバックオフで再試行します。再試行後にサービス呼び出しが失敗すると、ワークフローは を使用してサービスのCircuitStatus
テーブルにレコードを挿入しExpiryTimeStamp
、ワークフローは FAIL
状態で終了します。同じサービスへの後続の呼び出しは、サーキットブレーカーが開いている限り、即時の障害を返します。ステートマシン定義のGet Circuit Status
ステップは、 ExpiryTimeStamp
値に基づいてサービスの可用性をチェックします。期限切れの項目は、DynamoDB の有効期限 (TTL) 機能を使用してCircuitStatus
テーブルから削除されます。
「サンプルコード」
次のコードでは、GetCircuitStatus
Lambda 関数を使用してサーキットブレーカーのステータスを確認します。
var serviceDetails = _dbContext.QueryAsync<CircuitBreaker>(serviceName, QueryOperator.GreaterThan, new List<object> {currentTimeStamp}).GetRemainingAsync(); if (serviceDetails.Result.Count > 0) { functionData.CircuitStatus = serviceDetails.Result[0].CircuitStatus; } else { functionData.CircuitStatus = ""; }
次のコードは、Step Functions ワークフローの Amazon States Language ステートメントを示しています。
"Is Circuit Closed": { "Type": "Choice", "Choices": [ { "Variable": "$.CircuitStatus", "StringEquals": "OPEN", "Next": "Circuit Open" }, { "Variable": "$.CircuitStatus", "StringEquals": "", "Next": "Execute Lambda" } ] }, "Circuit Open": { "Type": "Fail" }
GitHub リポジトリ
このパターンのサンプルアーキテクチャの完全な実装については、https://github.com/aws-samples/circuit-breaker-netcore-blog