リモート サービスまたはリソースとの接続時に、復旧に要する時間が一定しないエラーを処理します。 このパターンにより、アプリケーションの安定性と回復性が向上します。
分散環境では、低速なネットワーク接続、タイムアウト、リソースのオーバーコミットや一時的な使用不能などの一時的な障害が原因で、リモート リソースとサービスの呼び出しが失敗する可能性があります。 このようなエラーは、通常は短時間で自動的に修正され、堅牢なクラウド アプリケーションでは、再試行パターンなどの方法を使用して、これらのエラーを処理する準備が整っている必要があります。
ただし、エラーが予期しないイベントによるものであることや、修正にかなり時間がかかる可能性があることも考えられます。 このような障害の重大度は、部分的な接続の損失からサービスの完全な不具合まで多岐にわたります。 このような状況では、アプリケーションが成功する可能性が低い操作を継続的に再試行するのは無意味な場合があります。代わりに、アプリケーションは操作が失敗したことを迅速に受け入れ、それに応じてこのエラーを処理する必要があります。
さらに、サービスが非常にビジーな状態の場合は、システムの一部分のエラーが障害の連鎖につながる可能性があります。 たとえば、サービスを呼び出す操作は、タイムアウトを実装するように構成し、サービスがこの期間内に応答できない場合はエラー メッセージで応答するように構成できます。 ただし、この方法では、タイムアウト期間が経過するまで、同じ操作に対する多数の同時要求がブロックされる可能性があります。 これらのブロックされた要求が、重要なシステム リソース (メモリ、しきい値、データベース接続など) をとどめてしまう可能性があります。 そのため、これらのリソースが使い果たされ、同じリソースを使用する必要があるシステムの他の関係のない部分で障害が発生する可能性があります。 このような場合は、操作がすぐに失敗し、成功する可能性がある場合はサービスの呼び出しを試みるだけのほうが望ましいでしょう。 タイムアウトを短く設定すると、この問題を解決するのに役立つ場合がありますが、タイムアウトが短くならず、サービスへの要求が最終的に成功した場合でも、ほとんどの場合、操作が失敗します。
サーキット ブレーカー パターンを使用すると、失敗する可能性のある操作をアプリケーションが繰り返し実行することを防ぐことができます。 障害が長期間にわたると判断している間に、エラーが修正されたり CPU サイクルが浪費されたりするのを待つことなく、続行することができます。 サーキット ブレーカー パターンでは、エラーが解決されたかどうかをアプリケーションで検出することもできます。 問題が解決済みのように見える場合、アプリケーションは操作の呼び出しを試みることができます。
サーキット ブレーカー パターンの目的は、再試行パターンとは異なります。 再試行パターンでは、アプリケーションが成功を見込んで操作を再試行することができます。 サーキット ブレーカー パターンは、失敗する可能性がある操作をアプリケーションが実行しないようにします。 アプリケーションは、サーキット ブレーカーによって操作を呼び出す再試行パターンを使用することで、これら 2 つのパターンを組み合わせることができます。 ただし、再試行ロジックは、サーキット ブレーカーによって返されるすべての例外から大きな影響を受け、エラーが一時的なものではないことが示されると、再試行回数を破棄します。
サーキット ブレーカーは、失敗する可能性のある操作のプロキシとして機能します。 プロキシは、発生した最近のエラーの数を監視し、この情報を使用して、操作の続行を許可するか、すぐに例外を返すかを決定する必要があります。
プロキシは、電路遮断器の機能を模倣する、次の状態のステート マシンとして実装できます。
クローズド: アプリケーションからの要求は、操作にルーティングされます。 プロキシは最近のエラーの数のカウントを保持し、操作への呼び出しが成功しなかった場合、プロキシはこのカウントを増分します。 最近のエラーの数が指定された期間内に指定されたしきい値を超えると、プロキシはオープン状態になります。 この時点でプロキシはタイムアウト タイマーを開始し、このタイマーの有効期限が切れると、プロキシは Half-Open 状態になります。
タイムアウト タイマーの目的は、アプリケーションがもう一度操作を実行する前に、障害の原因となった問題を解決するための時間をシステムに提供することです。
オープン: アプリケーションからの要求はすぐに失敗し、アプリケーションに例外が返されます。
ハーフオープン: アプリケーションからの限られた数の要求が、操作のパス スルーと呼び出しを許可されます。 これらの要求が成功した場合、以前にエラーの原因となった障害は既に修正されている見なされ、サーキット ブレーカーはクローズド状態に切り替わります (エラー カウンターはリセットされます)。 要求が失敗した場合、サーキット ブレーカーは障害が引き続き存在することを前提とするため、オープン 状態に戻り、タイムアウト タイマーを再起動して、システムが障害から復旧するためのさらに時間を与えます。
ハーフオープン状態は、復旧中のサービスに突然大量の要求が送信されないようにするために役立ちます。 サービスの復旧中は、復旧が完了するまでは限られた量の要求に対応できますが、復旧の進行中は大量の作業によってサービスがタイムアウトになったり、再び失敗したりする可能性があります。
この図では、クローズド状態で使用されるエラー カウンターは時間ベースです。 これは定期的な間隔で自動的にリセットされます。 この設計は、サーキット ブレーカーが不定期に障害が発生した場合に オープン 状態に入らないようにするのに役立ちます。 サーキット ブレーカーをオープン状態にトリップするエラーのしきい値に達するのは、指定された期間の間に指定された数のエラーが発生したときにのみです。 ハーフオープン状態で使用されるカウンターは、操作の呼び出しに成功した試行の数を記録します。 サーキット ブレーカーは、指定された数の連続した操作の呼び出しが成功した後、クローズド状態に戻ります。 呼び出しが失敗すると、サーキット ブレーカーはオープン状態に入り、次にハーフオープン状態に入ったときに成功カウンターがリセットされます。
システムの復旧は、障害が発生したコンポーネントを復元または再起動するか、ネットワーク接続を修復することで、外部的に処理される可能性があります。
サーキット ブレーカー パターンにより、エラーからのシステムの復旧中の安定性が保たれ、パフォーマンスに対する影響が最小限に抑えられます。 これにより、失敗する可能性がある操作の要求を、操作がタイムアウトになるまで待機したり返さないようにしたりするのではなく、すぐに拒否することによって、システムの応答時間を維持することができます。 状態が変化するたびにサーキット ブレーカーでイベントが発生する場合は、この情報を使用して、サーキット ブレーカーによって保護されているシステムの一部の正常性を監視したり、サーキット ブレーカーがオープン状態にトリップするときに管理者に警告したりできます。
このパターンはカスタマイズ可能で、可能性のあるエラーの種類に応じて適用できます。 たとえば、サーキット ブレーカーにタイムアウト タイマーを増やすことができます。 最初に数秒間、サーキット ブレーカーを Open 状態にして、障害が解決されていない場合は、タイムアウトを数分に増やします。 場合によっては、エラーを返し例外を発生させるオープン状態ではなく、アプリケーションにとって意味がある既定値を返すほうが有益な場合もあります。
注意
従来、サーキット ブレーカーは、障害数やタイムアウト期間などの事前構成済みのしきい値に依存していたため、決定論的ですが、最適でない場合があります。 ただし、AI と ML を使用したアダプティブ手法では、リアルタイムのトラフィック パターン、異常、および過去の障害率に基づいてしきい値を動的に調整できるため、サーキット ブレーカーの回復性と効率が向上します。
このパターンの実装方法を決めるときには、以下の点に注意してください。
例外処理: サーキット ブレーカーを介して操作を呼び出すアプリケーションは、操作が使用できない場合に発生する例外を処理するように準備する必要があります。 例外の処理方法はアプリケーション固有になります。 たとえば、アプリケーションは、その機能を一時的に低下させたり、同じタスクの実行や同じデータの取得を試みる代替の操作を呼び出したり、ユーザーに例外を報告して後でもう一度やり直すよう求めたりすることがあります。
例外の種類: 要求はさまざまな理由で失敗する可能性があり、その一部は他の例外よりも重大な種類の失敗を示している可能性があります。 たとえば、リモート サービスがクラッシュし、復旧に数分かかる場合や、サービスが一時的にオーバーロードされているためにタイムアウトが発生したため、要求が失敗する可能性があります。 サーキット ブレーカーは、発生する例外の種類を確認し、その例外の性質に応じて戦略を調整できる場合があります。 たとえば、サービスが完全に使用できないための障害の数と比較して、サーキット ブレーカーを Open 状態にトリップするには、タイムアウト例外の数が多い必要があります。
監視: サーキット ブレーカーは、失敗した要求と成功した要求の両方を明確に監視し、運用チームがシステムの正常性を評価できるようにする必要があります。 分散トレースを使用して、サービス間でエンドツーエンドの可視性を実現します。
回復可能性: 保護している操作の復旧パターンと一致するようにサーキット ブレーカーを構成する必要があります。 たとえば、サーキット ブレーカーが長期間オープン状態のままの場合は、エラーの原因が解決されているとしても、例外が発生する可能性があります。 同様に、オープン状態からハーフオープン状態に切り替えるのが早すぎると、サーキット ブレーカーが変動し、アプリケーションの応答時間を短くすることがあります。
失敗した操作のテスト: タイマーを使用して ハーフオープン 状態に切り替えるタイミングを決定するのではなく、オープン 状態では、サーキット ブレーカーはリモート サービスまたはリソースに定期的に ping を実行して、再び使用可能になるかどうかを判断できます。 この ping は、以前に失敗した操作の呼び出しを試みる形で行われることも、「正常性エンドポイント監視パターン」に記載されている、サービスの正常性のテスト専用のリモート サービスによって提供される、特殊な操作を使用することもあります。
手動オーバーライド: 障害が発生した操作の復旧時間が非常に変動するシステムでは、管理者がサーキット ブレーカーを閉じて (障害カウンターをリセットする) 手動リセット オプションを提供すると便利です。 同様に、管理者は、サーキット ブレーカーによって保護された操作が一時的に使用できない場合に、サーキット ブレーカーを Open 状態に強制 (およびタイムアウト タイマーを再起動する) 可能性があります。
コンカレンシー: アプリケーションの多数の同時実行インスタンスから同じサーキット ブレーカーにアクセスできます。 この実装は、同時要求をブロックしたり、操作へのそれぞれの呼び出しに過剰なオーバーヘッドを加えたりしません。
リソースの区別: 基になる独立したプロバイダーが複数存在する可能性がある場合は、1 種類のリソースに対して 1 つのサーキット ブレーカーを使用する場合は注意してください。 たとえば、複数のシャードが含まれているデータ ストアでは、あるシャードで一時的な問題が発生しているときに、別のシャードには完全にアクセス可能であることがあります。 このようなシナリオのエラー応答が統合されると、アプリケーションは、エラーの可能性が高いときでも一部のシャードへのアクセスを試みる一方、他のシャードへのアクセスは、成功する可能性があってもブロックすることがあります。
高速回線切断: 障害応答には、サーキット ブレーカーがすぐにトリップし、最小限の時間トリップし続けるのに十分な情報が含まれている場合があります。 たとえば、過負荷になっている共有リソースからのエラー応答で、即時の再試行が推奨されず、代わりに、アプリケーションが数分後にもう一度試みることを示されることがあります。
複数リージョンのデプロイ: サーキット ブレーカーは、単一リージョンまたは複数リージョンのデプロイ用に設計できます。 後者は、グローバル ロード バランサーまたはカスタムリージョン対応の回線ブレーク戦略を使用して実装でき、制御されたフェールオーバー、待機時間の最適化、規制コンプライアンスを保証します。
サービス メッシュサーキットブレーカー:サーキット ブレーカーは、アプリケーション層で実装することも、横断的で抽象化された機能として実装することもできます。 たとえば、サービス メッシュは、多くの場合、サイドカー として、またはアプリケーション コードを変更せずにスタンドアロン機能として、サーキット ブレークをサポートします。
注意
クライアントを調整している場合はサービスから HTTP 429 (要求が多すぎます) が返され、サービスが現在使用できない場合は HTTP 503 (サービス利用不可) が返される可能性があります。 応答には、予想される遅延時間などの追加情報を含めることができます。
失敗した要求の再生: オープン 状態では、サーキット ブレーカーは単にすばやく失敗するのではなく、各要求の詳細をジャーナルに記録し、リモート リソースまたはサービスが使用可能になったときにこれらの要求が再生されるように調整することもできます。
外部サービスの不適切なタイムアウト: サーキット ブレーカーは、長いタイムアウト期間で構成された外部サービスで失敗した操作からアプリケーションを完全に保護できない可能性があります。 タイムアウトが長すぎる場合は、サーキット ブレーカーが操作に失敗したことをサーキット ブレーカーが示す前に、サーキット ブレーカーを実行しているスレッドが長時間ブロックされる可能性があります。 この時点では、他の多くのアプリケーション インスタンスもサーキット ブレーカーによってサービスを呼び出そうとして、すべてが失敗するまで多数のスレッドを占有することがあります。
コンピューティングの多様化への適応性: サーキット ブレーカーは、サーバーレスからコンテナー化されたワークロードまで、さまざまなコンピューティング環境を考慮する必要があります。コールド スタートやスケーラビリティなどの要因が障害処理に影響を与えます。 アダプティブ アプローチでは、コンピューティングの種類に基づいて戦略を動的に調整できるため、異種アーキテクチャ間で回復性を確保できます。
このパターンは次の目的で使用します。
- リモート サービスによる過剰な呼び出しを停止したり、これらの操作が失敗する可能性が高い場合に共有リソースへのアクセス要求を停止したりして、連鎖障害を防ぐため。
- リアルタイム障害信号に基づいてトラフィックをインテリジェントにルーティングすることで、複数リージョンの回復性を強化します。
- 低速な依存関係から保護し、サービス レベルの目標 (SLO) に対応し、待ち時間の長いサービスによるパフォーマンスの低下を回避するのに役立ちます。
- 断続的な接続の問題を処理し、分散環境での要求エラーを減らす。
このパターンは次の場合は推奨されません。
- メモリ内データ構造など、アプリケーションのローカルのプライベート リソースへのアクセスを処理する場合。 この環境では、サーキット ブレーカーを使用すると、システムにオーバーヘッドが加わることがあります。
- 例外をアプリケーションのビジネス ロジックで処理する代わりとして。
- 既知の再試行アルゴリズムで十分であり、依存関係が再試行メカニズムに対処するように設計されている場合。 この場合、アプリケーションにサーキット ブレーカーを実装すると、不要な複雑さがシステムに追加される可能性があります。
- サーキット ブレーカーのリセットを待機すると、許容できない遅延が発生する可能性があります。
- メッセージ ドリブンアーキテクチャまたはイベントドリブン アーキテクチャがある場合、失敗したメッセージは手動処理または遅延処理のために配信不能キュー (DLQ) にルーティングされることが多いためです。 通常、これらの設計で実装される組み込みの障害分離と再試行メカニズムで十分です。
- グローバル ロード バランサーやサービス メッシュの正常性チェックなど、インフラストラクチャまたはプラットフォーム レベルで障害復旧が管理されている場合、サーキット ブレーカーは必要ない可能性があります。
設計者は、Azure Well-Architected Framework の柱で説明されている目標と原則に対処するために、ワークロードの設計で回路ブレーカーのパターンをどのように使用できるかを評価する必要があります。 次に例を示します。
重要な要素 | このパターンが柱の目標をサポートする方法 |
---|---|
信頼性設計の決定により、ワークロードが誤動作に対して復元力を持ち、障害発生後も完全に機能する状態に回復することができます。 | このパターンにより、障害依存性のオーバーロードが防止されます。 このパターンを使用して、ワークロードのグレースフルな低下をトリガーすることもできます。 サーキットブレーカは、自己保存とセルフヒーリングの両方を提供するために、多くの場合自動回復と結合されます。 - RE: 03 障害モード分析 - RE:07 一時的な障害 - RE:07 自己保護 |
パフォーマンスの効率化は、スケーリング、データ、コードを最適化することによって、ワークロードが効率的にニーズを満たすのに役立ちます。 | このパターンは、エラー時の再試行アプローチを回避し、依存関係のリカバリ中に過剰なリソース使用率につながる可能性があり、リカバリを試行している依存関係でのパフォーマンスが過負荷になることもあります。 - PE:07 コードとインフラストラクチャ - PE:11 ライブ問題の応答 |
設計決定と同様に、このパターンで導入される可能性のある他の柱の目標とのトレードオフを考慮してください。
このパターンを実装する場合は、次のパターンも役に立つことがあります。
信頼性の高い Web アプリ パターンでは、クラウドに収束する Web アプリケーションにサーキット ブレーカー パターンを適用する方法を示します。
再試行パターン。 失敗した操作を透過的に再試行することで、サービスまたはネットワーク リソースに接続しようとする際に、予測される一時的な障害をアプリケーションがどのように処理できるかを説明しています。
正常性エンドポイントの監視パターン。 サーキット ブレーカーは、サービスによって公開されるエンドポイントに要求を送信することで、サービスの正常性をテストできることがあります。 サービスは、その状態を示す情報を返す必要があります。