マイクロサービス障害隔離のためのサーキットブレーカーパターンと状態遷移
サーキットブレーカーは失敗が続く依存先への呼び出しを制限し、障害の波及を抑える設計パターンです。Closed・Open・Half-Openは一般的な実装例で、閾値や遷移は設計ごとに異なります。
発行・訂正窓口:infostoa · 編集基準
この記事の個別の執筆者・専門査読者の情報は提供されていません。
1. 応答の遅い依存先が呼び出し元の資源を占有する場合
依存先の応答が遅い、または返らないと、呼び出し元はタイムアウトまでスレッドや接続を占有することがあります。同時呼び出しが増えると、同じ資源を使う別の処理にも影響し得ます。サーキットブレーカーは、観測した失敗が設定した条件に達した後、呼び出しを一時的に拒否して待機や再試行の負荷を抑える方法の一つです。影響範囲や回復の結果は呼び出し構造と方針によって異なり、一つの依存先の障害がシステム全体を必ず停止させるわけではありません。
電気ブレーカーにたとえた図です。特定のソフトウェアライブラリーの状態遷移や方針を示すものではありません。
2. サーキットブレーカーの3状態マシン:Closed、Open、Half-Openの遷移規則
サーキットブレーカーは、選んだ障害の兆候が続く依存先への呼び出しを一時的に制限し、呼び出し側と下流サービスの資源消費や障害の波及を抑えるパターンです。Martin Fowlerの2014年の記事は簡潔な実装例を示し、Michael Nygardの著書『Release It!』がパターンを広めたと記しています。Closed・Open・Half-Openは一般的な状態モデルですが、すべてのライブラリで固定された三状態機械という意味ではありません。通常時の「閉(Closed)」状態ではすべてのリクエストを下流サービスへ通します。失敗の件数または割合をどの期間・条件で集計するかは、実装ごとのポリシーによって異なります。
3. エラー率判定ウィンドウ、タイムアウト設計、および自動復旧タイマー
しきい値の方式は実装と障害信号によって異なります。Fowlerの簡潔なRuby例は失敗率50%を使っていません。Timeout::Errorを数え、しきい値5に達すると回路を開き、呼び出しが成功するとカウンターを0に戻します。50%は記事の後半で、より高度な別案として紹介されています。いずれも推奨初期値ではありません。Microsoftも観測期間内のしきい値を説明しますが、共通の期間や標本数は定めていません。実際の通信量に合わせて期間、最小標本数、遅延条件、集計するエラーを決め、通常の業務上の拒否や入力誤りは依存先障害から除外します。
仮想ポリシーで判定を具体化します。「判定対象の依存先呼び出しが10件以上になってから失敗率50%を評価し、通常の業務上の拒否は分母に含めない」とします。9件中5件が失敗しても最小標本数に届かないため、回路は開かず観測を続けます。対象となる10件のうちタイムアウトが5件、成功が5件なら、この例のポリシーは回路を開きます。数値は説明用で推奨値ではありません。実際のライブラリーが同じ観測窓、最小標本数、エラー除外条件を備えているか確認してください。
再試行とブレーカーは役割が異なります。再試行は一時的な失敗が次の試行で回復することを期待しますが、ブレーカーは失敗が続いて成功しにくい呼び出しを止めます。併用時は、ブレーカーが一時的でない障害を示して開いた後、再試行ループが要求を続けないよう連携します。そうしないと、負荷を減らす仕組みの横で呼び出し元が要求を積み増すおそれがあります。
ブレーカーが開いた後の即時失敗だけでなく、保護対象の呼び出し自体のタイムアウトも重要です。時間制限が長すぎると、しきい値に達する前に多くの要求がスレッドや接続を占有し続けます。MicrosoftとFowlerはいずれも、リモート応答を待つことが資源を消費し、連鎖障害につながる可能性を説明します。呼び出し時間と失敗集計が資源予算内で働くか確認します。
4. 遮断後の応答と障害範囲を決める
設計上の焦点は遮断後の応答契約です。読み取りに古いデータを明示して返せるか、安全な書き込みをキューへ送れるか、エラーを返すべきかを処理ごとに決めます。Half-Openは回復中の依存先へ限られた試験要求を通し、一度に負荷が集中するのを抑える方法です。許可数や再開放条件は実装ごとに異なります。Microsoftの説明は同文書のモデル内で試験失敗後に再開放し、Fowlerの簡潔な例は失敗後に待ち時間を再設定します。これらを全ライブラリーの不変規則として扱いません。
状態遷移と成功・失敗を記録すれば、しきい値が依存先の状態に合うか確認できます。独立したシャードや複数の供給先がある場合、ひとつのブレーカーが正常な資源まで止めないよう障害範囲を分けます。複数インスタンス間の状態共有は一貫性の必要性と遅延・可用性の費用で決める設計選択で、パターンの必須要件ではありません。 例えば独立したデータシャードの失敗を一つのカウンターにまとめると、一部の障害で正常なシャードへの呼び出しまで止まる場合があります。失敗を集計する単位は実際の依存先の境界に合わせます。