コンテンツにスキップ

回復方法@信頼性

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01 回復方法の設計

複数の回復方法のパターンを組み合わせる。


02. ヘルスチェックパターン

ヘルスチェックパターンとは

ヘルスチェックは、宛先に定期的にリクエストを送信し、レスポンスの内容に応じて正常性を検証するデザインパターンである。


アクティブ

  • HTTP (HTTPS)
  • DNS
  • TCP (UDP)
  • 独自プロトコル


パッシブ


03. リトライパターン

リトライとは

処理が失敗した場合に、一時的な問題に起因している可能性を考慮して、再実行によって処理の成功を試みるデザインパターンである。


04. タイムアウトパターン

タイムアウトパターンとは

タイムアウトは、時間のかかる処理(例:通信、DB操作、ファイル操作、計算など)に制限時間を設けるデザインパターンである。

これにより、時間のかかる処理がハードウェアリソースを使用し続けることを防ぎ、他の処理にハードウェアリソースを譲る。


タイムアウト時間

▼ マイクロサービスだけに着目する場合

送信元マイクロサービスよりも宛先マイクロサービスのタイムアウト時間を短くする。

マイクロサービス # 45秒
⬇⬆️︎
⬇⬆️︎︎︎
マイクロサービス # 30秒
⬇⬆️︎
⬇⬆️︎
マイクロサービス # 15秒

▼ サイドカープロキシにも着目する場合

送信元マイクロサービスよりもサイドカーのタイムアウト時間を短くする。

また、サイドカーよりも宛先マイクロサービスのサイドカーのタイムアウト時間を短くする。

アプリ # 45秒
⬇⬆️︎
⬇⬆️︎
サイドカー # 44秒
⬇⬆️︎
-------------- # マイクロサービス間の境界
⬇⬆️︎
サイドカー # 31秒
⬇⬆️︎
⬇⬆️︎
アプリ # 30秒
⬇⬆️︎
⬇⬆️︎
サイドカー # 29秒
⬇⬆️︎
-------------- # マイクロサービス間の境界
⬇⬆️︎
サイドカー # 16秒
⬇⬆️︎
⬇⬆️︎
アプリ # 15秒


タイムアウトの種類

▼ 処理タイムアウト

任意の処理の完了を待機する最大時間である。

▼ 接続タイムアウト (Connection timeout)

『オープンタイムアウト (Open timeout) 』ともいう

通信処理において、スリーウェイハンドシェイクの確立を試みてから、接続の確立が成功/失敗するまでの最大待機時間である。

TCP接続の確立中、メモリ上で送信データが保持されており、占有されてしまっている。

これを解放する必要がある。

▼ 読み取りタイムアウト (Read timeout)

通信処理において、接続が確立後に宛先にリクエストが到達してから、レスポンスの返信を待機するまでの最大待機時間である。

これの場合、サーバーにリクエストを送信できており、サーバーがレスポンスを返信できない状態にある。

HTTPリクエストのステータスコードでは、Gateway Timeout (504) が相当する。

▼ セッションタイムアウト (Session timeout)

通信処理において、L7のプロトコル(例:HTTP、HTTPS、SMTP、DNS、POP3など)による認証後に、無通信状態(パケットの送受信がない状態)や経過時間を猶予する最大時間である。

▼ アイドルタイムアウト (Idle timeout)

通信処理において、L4のプロトコル(例;TCP、UDPなど)による接続中に無通信状態(パケットの送受信がない状態)を猶予する最大時間である。


05. サーキットブレイカーパターン

サーキットブレイカーパターンとは

サーキットブレイカーは、レスポンスを対象とした外れ値(例:500系ステータスコード率、Gateway系ステータス率、接続プール上限)が閾値を超過した場合に、宛先を指定した期間だけ排除(Eject)し、回復を待機するデザインパターンである。

マイクロサービス間の通信方式がリクエスト−レスポンスパターンの場合に、リクエストの場合には連鎖的な障害(カスケード障害)が起こるため、これに対処する必要がある。

宛先マイクロサービスからのレスポンスに外れ値の閾値を設定しておく。

運用中にこれを超過すると、送信元マイクロサービスはタイムアウトになるまで処理を待機する。

その間、送信元マイクロサービスは他の処理を実行できなくなってしまうため、これを防ぐ。


仕組み

  1. 宛先マイクロサービスからのレスポンスが外れ値の閾値を超過する。
  2. 宛先マイクロサービスを排除し、特定のエラーステータス (503など) でレスポンスを返信する。
  3. 障害の起こったマイクロサービスを指定された期間排除する。
  4. 障害が回復次第、
  5. を再開する。

blast-radiusを最小限にできる。

circuit-breaker


06. フォールバックパターン

フォールバックパターンとは

フォールバックパターンは、エラーハンドリングの方法の一つである。

リトライの失敗やサーキットブレイカーで宛先マイクロサービスからデータを取得できなかった場合に、代わりにデータを返信するデザインパターンである。


具体例

正常系の代わりとなるデータとして、例えば以下があります。

  • 静的ファイル
  • キャッシュを使用した前回の処理結果
  • ユーザーによらないデータ (広告、ランキングなど)


07. バルクヘッドパターン

バルクヘッドパターンは、遮断壁(バルクヘッド)をもつ区画を設け、ハードウェアリソースや接続プールの制限を区画間で分離するデザインパターンである。これにより、他の区画への影響を防ぐ。

区画はマイクロサービスの分割単位 (例:境界づけられたコンテキスト) に合わせるとよい。


08. レートリミットパターン

特定のユーザーが期間内に閾値以上の数のリクエストを送信した場合、そのユーザーからのリクエストを遮断したり、リクエストの処理速度を低下させるデザインパターンである。


09. ロードシェディングパターン (Load Shedding)

マイクロサービスが過負荷になった場合に、優先度の低い機能に対するリクエストを拒否し、優先度の高い機能のみを実施するようにするデザインパターンである。


10. キャッシュパターン

頻繁に使用するデータや処理結果をマイクロサービスのメモリに保存し、他のマイクロサービスやDBへの接続を最小限に抑える。


11. エラーとエラーハンドリング

エラーとは

プログラムの実行が強制的に停止されるランタイムエラー (実行時エラー) 、停止せずに続行される非ランタイムエラー、に分類される。


エラーハンドリングの意義

▼ DBにとって

DB更新系の処理の途中にエラーが発生すると、DBが中途半端な更新状態になってしまう。

そのため、メソッドコールしたクラスでエラーを検出し、これをきっかけにロールバック処理を実行する必要がある。

注意点として、下層クラスのエラーの内容自体は握りつぶさずに、スタックトレースとしてメソッドコールしたクラスでロギングしておく。

▼ ソフトウェア開発者にとって

エラーが画面上に返却されたとしても、これはソフトウェア開発者にとってわかりにくい。

そのため、エラーをメソッドコールしたクラスで検出し、ソフトウェア開発者にわかる言葉に変換した例外としてスローする必要がある。

注意点として、下層クラスのエラー自体は握りつぶさずに、スタックトレースとしてメソッドコールしたクラスでロギングしておく。

▼ ユーザーにとって

エラーが画面上に返却されたとしても、ユーザーにとっては何が起きているのかわからない。

また、エラーをメソッドコールしたクラスで検出し、例外としてスローしたとしても、ソフトウェア開発者にとっては理解できるが、ユーザーにとっては理解できない。

そのため、例外スローを別の識別子 (例:boolean値) に変えてメソッドコールしたクラスに持ち上げ、最終的には、これをポップアップなどでわかりやすく通知する必要がある。

これらは、サーバーサイドのtry-catch-finally文や、フロントエンドのポップアップ処理で実現する。

注意点として、子クラスのエラー自体は握りつぶさずに、スタックトレースとしてメソッドコールしたクラスでロギングしておく。


エラーハンドリングのステップ

エラーハンドリングは以下の4ステップからなる。

(1)

エラー検出

(2)

例外スロー

(3)

例外キャッチ

(4)

ロギング


エラーのエスカレーション

▼ マイクロサービス内

マイクロサービス内では、例外でエラーをエスカレーションする。

各レイヤーでは例外をスローするだけに留まり、スローされた例外を対処する責務は、より上位レイヤーに持たせる。

より上位レイヤーでは、そのレイヤーに合った例外に詰め替えて、これをスローする。

▼ マイクロサービス間

マイクロサービス間では、ステータスコードでエラーをエスカレーションする。

宛先のマイクロサービスから受信したステータスコードは、送信元にそのまま返信するように設計する。

最終的に、フロントエンドアプリでステータスコードをユーザーにわかるメッセージに変換する。

microservices_status-code_propagation

▼ フロントエンド領域とマイクロサービス領域間

フロントエンドは、マイクロサービスからエスカレーションされたステータスコードを取得し、画面上のポップアップで警告文として表示する。