645 文字
3 分
サーキットブレーカーで障害の連鎖を止める
サーキットブレーカーは、電気のブレーカーと同じ発想で名付けられたデザインパターンです。下流のサービスが落ちている/極端に遅い状況で、こちらが律儀に呼び出しを続けてしまうと、
- スレッドが詰まる
- コネクションが枯渇する
- リトライ嵐でさらに下流を追い込む
という連鎖障害(カスケード障害)が起きます。これを防ぐために「しばらく呼ぶのをやめる」判断を自動でしてくれるのが、サーキットブレーカーです。
3つの状態
サーキットブレーカーは、典型的には次の3つの状態を行き来します。
Closed(通常運転)
呼び出しはそのまま通します。ただし、成功/失敗を内部でカウントし、失敗率や連続失敗回数がしきい値を超えると、状態を Open に切り替えます。
Open(遮断中)
実際の呼び出しを行わず、即座にエラーを返します。下流に余計な負荷をかけないので、相手が回復する時間を稼げます。一定時間が経つと、Half-Open に移行します。
Half-Open(試運転)
少数のリクエストだけ実際に通してみて、成功すれば Closed に戻し、まだダメなら Open に戻します。「治ったかどうか」を安全に確かめるフェーズです。
フォールバック設計とセット
ブレーカーが Open のときに即エラーで返すだけだと、ユーザー体験はあまり良くありません。可能であれば フォールバック を用意します。
- キャッシュした結果を返す
- 簡略化したレスポンスで返す
- 「あとで通知します」と非同期に倒す
呼び出し元が「ダメだったときに何を出すか」までセットで考えるのが、レジリエンスを上げるコツです。
実装例
- 歴史的には Netflix の Hystrix。今はメンテモード。
- JVM 系では Resilience4j。
- 言語非依存に統一したいなら、サービスメッシュ(Istio、Linkerd、Envoy)に任せる選択肢もある。
やりすぎ注意
- しきい値が厳しすぎると、ちょっとした揺らぎでも遮断されてしまう。
- ブレーカーは「下流を守る」ことはせず、「自分を守る」だけだと割り切る。下流の保護はレートリミットや並行数制限が担当。
- タイムアウト・リトライ・バルクヘッド(隔離)と組み合わせて初めて、まともなレジリエンスになる。
「呼べばいつかは返ってくる」前提を一度捨て、「呼ばない判断」を組み込むのが、分散システム時代の基本姿勢になります。