HTTP通信のレジリエンス戦略
はじめに
耐障害性
や 可用性
の高いアプリケーションとは何か?
と問われると、インフラを主に担当してきた私にとっては、サーバの クラスター構成
や オートスケーリング
、バックアップ&リストア
などのキーワードが思い浮かびます...
しかし、本記事では、フロントエンド(クライアント)側において、耐障害性
や 可用性
の高いアプリケーションを構築する方法について紹介します!
現在、オンプレミス環境でアプリケーションを開発しているのですが、サーバのオートスケーリング機能は存在しなく... サーバの負荷によって一時的な通信断が容易に発生するからです
レジリエンス戦略とは
AKAが謎に面白かったです...w
機能 | 説明 | AKA |
---|---|---|
Retry | エラー時にリクエストを再試行 | たまたま調子が悪いだけかも |
Circuit Breaker | エラー時にリクエストを一定期間停止 | システムを休ませてあげよう |
Timeout | リクエストの最大処理時間を設定し、超過時にエラーをスロー | 永遠に待つわけにはいかない |
Rate Limiter | 一定時間内のリクエスト回数を制限 | ちょっと落ち着こうか |
Fallback | エラー時に代替処理を実行 | ダメでも他の方法がある |
Hedging | 複数のリクエストを並行して実行し、早いレスポンスを使用 | 念のため保険をかける |
実装例
C# Pollyというライブラリを使用し、回復性のあるHTTPリクエストを実装します
Retry
、Timeout
、Fallback
を組み合わせ、シンプルなHTTPリクエストを行うコンソールアプリケーションを作成します
後続のHTTPリクエストがあることを考慮し、複数回リクエストします
※リトライとは別です
-
Fallback
: 通信エラーやユーザによるキャンセル操作によりHttpResponseが得られなかった場合に代替のHttpResponseに置き換える -
OuterTimeout
: 全てのリクエスト(リトライ)における処理全体のTimeoutを設定する -
Retry
: エラーが発生した場合にHTTPリクエストを再試行する -
InnerTimeout
: 各リクエスト(リトライ)におけるTimeoutを設定する
-
正常/エラー応答時1
1回目のリクエストは、リトライせずに正常で終了
2回目のリクエストは、2回目のリトライで正常で終了
3回目のリクエストは、3回リトライしたが失敗で終了
-
正常/エラー応答時2
1回目のリクエストは、3回リトライしたが失敗で終了 ※通信エラーではないため、後続の処理は続行
2回目のリクエストは、3回目のリトライで正常で終了
3回目のリクエストは、リトライせずに正常で終了
-
通信エラー時
1回目のリクエストで、3回リトライしたが通信エラーだったため、後続の処理はせずに終了
-
処理全体でTimeout発生時
2回目のリトライ中に処理全体のTimeoutが発生したため、3回目のリトライはせずに終了
-
各リクエスト(リトライ)でTimeout発生時
-
ユーザのキャンセル操作時
サーバからのレスポンスを待たず、Fallback処理をして終了
おわりに
人気の生成AI、ChatGPTやClaudeなどをSaaSで利用する場合は、通信負荷などでエラー応答が高頻度で返されると思います
レジリエンス戦略を正しく構成し、ユーザエクスペリエンスを損なわないことが大切だと感じました
次回は、Progressive Web Apps を利用したオフライン対応/キャッシュ戦略を書きたいと考えています
Discussion