Azure SDK チームが、Azure Functions の Service Bus トリガーにおける指数バックオフ(Exponential Backoff)とサーキットブレーカー(Circuit Breaker)の実装パターンを公式サンプルとして公開した。分散システムにおけるリトライストームを制御し、依存サービスの保護と障害時の段階的縮退(Graceful Degradation)を実現する。

なぜ今これが必要か

Azure Functions は受信メッセージに対してスケールアウトを自動的に行う。これは高スループットを実現する強みだが、裏を返せばダウンストリームの依存サービスへ大量の同時リクエストを一気に集中させるリスクでもある。

たとえば、データベースが応答遅延を起こしているとき、Functions の全インスタンスが即座にリトライを繰り返すとどうなるか。Service Bus のキューは溜まり続け、再試行で消費されるコンピュートリソースは無駄になり、最終的には一時的な障害がシステム全体の障害に発展する。これがリトライストームだ。

2つのパターンの役割分担

指数バックオフ――「次はいつリトライするか」を制御する

指数バックオフは、リトライのたびに待機時間を指数関数的に増やすパターンだ。1回目の失敗後は5秒後、2回目は15秒後、3回目は45秒後……というように、依存サービスが回復する時間的余裕を与える。

Azure Functions + Service Bus の実装では、メッセージのアプリケーションプロパティにリトライカウントを持たせ、次回実行用のメッセージを指定時刻にスケジュールして現在のメッセージを完了(Complete)する。最大リトライ数を超えたメッセージはデッドレタキューへ退避する。


出典: この記事は Exponential backoff and circuit breaker for Service Bus-triggered Azure Functions の内容をもとに、筆者の見解を加えて独自に執筆したものです。