全2699文字
PR

 分散システム環境では、複数のコンポーネントがネットワークで接続されることで1つの大きなシステムが構成される。このような構成の場合、あるコンポーネントで発生した遅延やダウンがネットワークを経由して多くのコンポーネントに波及し、大規模なカスケード障害が発生してしまう。

 本番環境で使う各コンポーネントは、それぞれが冗長化されており、接続のたびに異なるノードに接続されるケースが一般的だ。このような場合は、レスポンスがなくタイムアウトしたり、接続エラーが発生したりするケースであっても、リトライすれば成功することが多い。

 一方、コンポーネントの先にあるデータベースが障害を起こしたケースなどでは、リトライして別のノードに接続されることを期待しても、別のノードでも同様にエラーとなる。このような場合、リトライを繰り返すとリクエスト数が何倍にも増幅され、障害がより深刻な状況になる。

 このような場合は、障害が発生したコンポーネントをシステムから一定時間切り離し、「一時的に利用不能」というエラー状態として取り扱うのが有効だ。こうすることで、ユーザーから次のリクエストを受け取ったとしても、エラー状態であるというレスポンスを即座に返すことができ、障害が連鎖してシステム全体がダウンするカスケード障害を防げる。

 障害が発生したコンポーネントを一定時間切り離す設計パターンを「サーキットブレーカーパターン」という。今回は、リモートサービスの障害を連鎖させないためのデザインパターンであるサーキットブレーカーを、Javaのライブラリー「Resilience4j」を利用して実際に実装してみよう。

サーキットブレーカーは3つの状態を取る

 サーキットブレーカーは、呼び出し先のコンポーネントの状態によって3つの状態を取る。

[画像のクリックで拡大表示]

 平常状態は、ブレーカーのスイッチが閉じているので「CLOSED」と呼ぶ。住宅などに設置されているブレーカーで例えると、電流が流れている状態だ。

 リモートコンポーネントの呼び出しが一定回数を超えると、ブレーカーが落ちて異常状態に移行する。これはスイッチが開いた状態なので「OPEN」と呼ぶ。

 異常状態になると一定時間、サーキットブレーカーはすべてのリクエストをエラーにして、呼び出し先コンポーネントに対する呼び出しを行わないようにする。これにより、呼び出し先コンポーネントが回復するための時間を稼ぐことができる。