645 文字
3 分
サーキットブレーカーで障害の連鎖を止める

サーキットブレーカーは、電気のブレーカーと同じ発想で名付けられたデザインパターンです。下流のサービスが落ちている/極端に遅い状況で、こちらが律儀に呼び出しを続けてしまうと、

  • スレッドが詰まる
  • コネクションが枯渇する
  • リトライ嵐でさらに下流を追い込む

という連鎖障害(カスケード障害)が起きます。これを防ぐために「しばらく呼ぶのをやめる」判断を自動でしてくれるのが、サーキットブレーカーです。

3つの状態#

サーキットブレーカーは、典型的には次の3つの状態を行き来します。

Closed(通常運転)#

呼び出しはそのまま通します。ただし、成功/失敗を内部でカウントし、失敗率や連続失敗回数がしきい値を超えると、状態を Open に切り替えます。

Open(遮断中)#

実際の呼び出しを行わず、即座にエラーを返します。下流に余計な負荷をかけないので、相手が回復する時間を稼げます。一定時間が経つと、Half-Open に移行します。

Half-Open(試運転)#

少数のリクエストだけ実際に通してみて、成功すれば Closed に戻し、まだダメなら Open に戻します。「治ったかどうか」を安全に確かめるフェーズです。

フォールバック設計とセット#

ブレーカーが Open のときに即エラーで返すだけだと、ユーザー体験はあまり良くありません。可能であれば フォールバック を用意します。

  • キャッシュした結果を返す
  • 簡略化したレスポンスで返す
  • 「あとで通知します」と非同期に倒す

呼び出し元が「ダメだったときに何を出すか」までセットで考えるのが、レジリエンスを上げるコツです。

実装例#

  • 歴史的には Netflix の Hystrix。今はメンテモード。
  • JVM 系では Resilience4j
  • 言語非依存に統一したいなら、サービスメッシュ(IstioLinkerdEnvoy)に任せる選択肢もある。

やりすぎ注意#

  • しきい値が厳しすぎると、ちょっとした揺らぎでも遮断されてしまう。
  • ブレーカーは「下流を守る」ことはせず、「自分を守る」だけだと割り切る。下流の保護はレートリミットや並行数制限が担当。
  • タイムアウト・リトライ・バルクヘッド(隔離)と組み合わせて初めて、まともなレジリエンスになる。

「呼べばいつかは返ってくる」前提を一度捨て、「呼ばない判断」を組み込むのが、分散システム時代の基本姿勢になります。