REL 5: 障害を緩和または耐えるために、分散システムの操作をどのように設計しますか?
分散システムは、サーバーやサービスなどのコンポーネントを相互接続するために通信ネットワークを利用しています。このネットワークでデータの損失やレイテンシーがあっても、ワークロードは確実に動作する必要があります。分散システムのコンポーネントは、他のコンポーネントやワークロードに悪影響を与えない方法で動作する必要があります。これらのベストプラクティスに従うことで、ワークロードはストレスや障害に耐え、より迅速に復旧し、そのような障害の影響を軽減できます。その結果、平均復旧時間 (MTTR) が向上します。
リソース
Retry, backoff, and jitter: AWS re:Invent 2019: Introducing The Amazon Builders’ Library
(DOP328)
Error Retries and Exponential Backoff in AWS
Amazon API Gateway: Throttle API Requests for Better Throughput
The Amazon Builders' Library: Timeouts, retries, and backoff with jitter
The Amazon Builders' Library: Avoiding fallback in distributed systems
The Amazon Builders' Library: Avoiding insurmountable queue backlogs
The Amazon Builders' Library: Caching challenges and strategies
Well-Architected lab: Level 300: Implementing Health Checks and Managing Dependencies
to Improve Reliability
CircuitBreaker (summarizes Circuit Breaker from “Release It!” book)
Michael Nygard “Release It! Design and Deploy Production-Ready Software”
ベストプラクティス:
-
該当するハードな依存関係をソフトな依存関係に変換するため、グレイスフルデグラデーションを実装する: コンポーネントの依存関係が異常な場合でも、コンポーネント自体は機能しますが、パフォーマンスが低下します。たとえば、依存関係の呼び出しが失敗した場合、事前に定義された静的レスポンスにフェイルオーバーします。
-
スロットルリクエスト: これは、予想外の需要の増加に対応するための軽減パターンです。一部のリクエストは受け入れられますが、定義された制限を超えるリクエストは拒否され、スロットルされたことを示すメッセージが返されます。クライアントの期待は、リクエストが戻されて放棄されるか、遅い速度で再試行することです。
-
再試行呼び出しを制御および制限する: エクスポネンシャルバックオフを使用して、徐々に長い間隔で再試行します。これらの再試行間隔をランダム化するジッターを導入し、再試行の最大数を制限します。
-
すぐに失敗し、キューを制限する: ワークロードがリクエストに正常に応答できない場合は、すぐに失敗するようにします。これにより、リクエストに関連付けられたリソースを解放でき、リソースが不足した場合にサービスを復旧できます。ワークロードは正常に応答できるが、リクエスト頻度が高すぎる場合は、代わりにキューを使用してリクエストをバッファします。ただし、長いキューは許可しないでください。クライアントがすでに処理を停止している古いリクエストを処理する原因となる可能性があるためです。
-
クライアントタイムアウトを設定する: タイムアウトを適切に設定し、体系的に検証します。デフォルト値の設定は通常高すぎるため、デフォルト値のままにしないでください
-
可能な場合はサービスをステートレスにする: サービスは、状態を必要としないようにするか、あるいは異なるクライアントリクエスト間で、ディスクまたはメモリにローカルに保存されたデータに依存しないように、状態をオフロードするかのいずれかにする必要があります。これにより、可用性に影響を与えることなく、サーバーをいつでも置き換えることができます。Amazon ElastiCache や Amazon DynamoDB は、オフロードした状態に適した宛先です。
-
緊急レバーを実装する: これは、ワークロードの可用性に対する影響を軽減できる可能性がある迅速なプロセスです。根本原因がなくても操作できます。緊急レバーは、完全に決定的なアクティブ化と非アクティブ化の基準を指定することにより、リゾルバーの認知負荷をゼロに減らせるものが理想的です。緊急レバーの例には、すべてのロボットトラフィックをブロックしたり、静的応答を行ったりすることが含まれます。緊急レバーは多くの場合手動ですが、自動化することもできます。
改善計画
該当するハードな依存関係をソフトな依存関係に変換するため、グレイスフルデグラデーションを実装する
- 静的レスポンスを返すことで、ワークロードは依存関係で発生する障害を軽減します
Well-Architected lab: Level 300: Implementing Health Checks and Managing Dependencies to Improve Reliability - 再試行オペレーションが失敗する可能性がある場合を検出し、クライアントがサーキットブレーカーパターンで失敗した呼び出しを行わないようにします。
CircuitBreaker
スロットルリクエスト
- Amazon API Gateway を使用する
Throttle API Requests for Better Throughput
再試行呼び出しを制御および制限する
Error Retries and Exponential Backoff in AWS
- Amazon SDK ではこれがデフォルトで実装されます。お客様独自の依存サービスを呼び出す場合は、同類のロジックを依存関係レイヤーに実装します。タイムアウトの時間と、再試行をいつ停止するのかをユースケースに基づいて決めます。
すぐに失敗し、キューを制限する
- サービスへの負荷が過剰になったときのフェイルファストを実装する
Fail Fast - キューを制限する: キューベースのシステムでは、処理が停止してもメッセージが到着し続けると、メッセージの負債が大きなバックログに蓄積され、処理時間が長くなることがあります。作業の完了が遅すぎて、結果が役に立たなくなることがあります。これにより、基本的にキューイングが防御することを意図していた、可用性への悪影響が発生します。
The Amazon Builders' Library: Avoiding insurmountable queue backlogs
クライアントタイムアウトを設定する
AWS SDK: Retries and Timeouts
可能な場合はサービスをステートレスにする
- リクエストパラメータに実際に格納できるステートを削除する
- 一部のデータ (Cookie など) は、ヘッダーまたはクエリパラメータで渡すことができます。
- リクエストですばやく渡すことができるステートを削除するためにリファクタリングします。
- ステートが必要かどうかを調べてから、エラーに強いマルチゾーンキャッシュまたはデータストアである Amazon ElastiCache、Amazon RDS、Amazon
DynamoDB、サードパーティー分散型データソリューションにステート追跡を移動します: 移動できないステートをエラーに強いデータストアに格納します。
- 実際には毎回のリクエストで必要のないデータはオンデマンドで取得できます。
- 非同期で取得できるデータを削除します。
- 必要なステートの条件を満たしているデータストアを決めます。
- リレーショナル型ではないデータには NoSQL データベースを検討します。
緊急レバーを実装する
- 緊急レバーを実装して使用するためのヒント
- 緊急レバーがアクティブになったら、実行数を増やすのではなく、減らす
- シンプルに保ち、バイモーダルな行動は避ける
- 緊急レバーを定期的にテストする
- これらは、緊急レバーではないアクションの例です
- キャパシティーを追加する
- サービスに依存するクライアントのサービス所有者を呼び出して、呼び出しを減らすよう依頼する
- コードを変更してリリースする