TT Lab
はじめる
学ぶ 学習パス コース

マイクロサービスアーキテクチャ

サーキットブレーカーの実装と状態遷移の検証

TT Labで続きを見る

目標

サーキットブレーカーを自分で実装して、CLOSED、OPEN、HALF_OPENの間の遷移を目で確認し、何を失敗として数えるかの決定が、なぜ最も重要かを、事故の事例で実感します。

なぜ重要なのか

サーキットブレーカーは、障害を直す仕組みではありません。障害が確実なときに素早く失敗して、呼び出し側のコネクションプールが枯渇しないように守る仕組みです。そのため、性能の指標ではなく、分離の指標で評価しなければなりません。実務でサーキットが生む事故は、ほとんどが2つです。1つ目は、4xxを失敗として集計して、正常なトラフィックまで遮断してしまうケースです。在庫サービスが特定の商品に400を返し始めたところ、サーキットが開いて、正常な商品の取得まで塞がれた事例があります。2つ目は、HALF_OPENの試験的な呼び出しを1件だけ許可して、OPENとHALF_OPENを行き来してフラッピングしてしまうケースです。このラボでは、その2つの落とし穴をそれぞれ1ステップずつ割り当てて、自分で作り、自分で防ぎます。

ステップ

  1. /opt/app/flaky.pyを127.0.0.1:8110で起動してください。GET /countが、これまでに受け取ったリクエスト数をJSONで返します。
  2. /root/cb/breaker.pyを作成して、/fastを3回呼び出してください。/root/cb/state.jsonに{"state":"CLOSED", ...}を書いてください。
  3. /always500を5回呼び出して、失敗率のしきい値を超えさせてください。設定は、ウィンドウ10、最小呼び出し数5、失敗率50%です。state.jsonのstateがOPENになります。
  4. OPENの状態で、さらに10回呼び出してください。/root/cb/fastfail.txtにbefore=<n> after=<n> blocked=10 max_ms=<밀리초>を書いてください(プレースホルダーはミリ秒です)。beforeとafterが同じで、max_msが50未満でなければなりません。
  5. waitDurationInOpenStateを3秒にして、3秒以上待った後に1回呼び出してください。state.jsonのstateがHALF_OPENになります。
  6. HALF_OPENで/fastを3回成功させて、CLOSEDに戻してください。permitted_in_half_openの値が3以上で記録されなければなりません。
  7. 新しいブレーカーで/bad(400)を10回呼び出してください。/root/cb/ignore4xx.jsonのstateは依然としてCLOSEDで、failuresは0でなければなりません。
  8. 全体のシナリオを一度に実行して、/root/cb/transitions.logにCLOSED->OPEN、OPEN->HALF_OPEN、HALF_OPEN->CLOSEDの3行を、この順序で残してください。

参考

ダウンストリームと呼び出しカウンターを準備する

/opt/app/flaky.pyを127.0.0.1:8110で起動してください。GET /countが、これまでに受け取ったリクエスト数をJSONで返します。

/opt/app/flaky.pyは、自分が受け取ったリクエスト数を/countで知らせます。この値が、後のステップで証拠になります。

CLOSED状態で通す

/root/cb/breaker.pyを作成して、/fastを3回呼び出してください。/root/cb/state.jsonに{"state":"CLOSED", ...}を書いてください。

状態をファイルに残さなければ、採点できません。状態の名前、失敗数、ウィンドウのサイズを、JSONで書いてください。

失敗率のしきい値でOPENにする

/always500を5回呼び出して、失敗率のしきい値を超えさせてください。設定は、ウィンドウ10、最小呼び出し数5、失敗率50%です。state.jsonのstateがOPENになります。

最小の呼び出し数を満たす前には、判定しません。ウィンドウ10、最小5、しきい値50%を、そのまま実装してください。

OPENではダウンストリームに行かないことを証明する

OPENの状態で、さらに10回呼び出してください。/root/cb/fastfail.txtにbefore=<n> after=<n> blocked=10 max_ms=<밀리초>を書いてください(プレースホルダーはミリ秒です)。beforeとafterが同じで、max_msが50未満でなければなりません。

遮断の前後で、ダウンストリームの呼び出しカウンターがそのままでなければなりません。そして、レスポンスがとても速くなければなりません。

待機時間の後にHALF_OPENへ遷移する

waitDurationInOpenStateを3秒にして、3秒以上待った後に1回呼び出してください。state.jsonのstateがHALF_OPENになります。

OPENに入った時刻を記録しておいて、経過を比較します。自動で遷移しなければ、人が介入することになってしまいます。

試験的な呼び出しの成功でCLOSEDに復帰する

HALF_OPENで/fastを3回成功させて、CLOSEDに戻してください。permitted_in_half_openの値が3以上で記録されなければなりません。

試験的な呼び出しの数を1にすると、フラッピングが起きます。なぜ3以上でなければならないのかを考えながら、実装してください。

4xxを失敗として数えない

新しいブレーカーで/bad(400)を10回呼び出してください。/root/cb/ignore4xx.jsonのstateは依然としてCLOSEDで、failuresは0でなければなりません。

400はクライアントの誤りなので、サーキットが介入することではありません。何を失敗と見なすかを、一覧で管理してください。

遷移履歴で総合的に検証する

全体のシナリオを一度に実行して、/root/cb/transitions.logにCLOSED->OPEN、OPEN->HALF_OPEN、HALF_OPEN->CLOSEDの3行を、この順序で残してください。

前のステップを1つのシナリオにつなげて、状態遷移が順番に記録されるようにしてください。