アプリケーションとインフラストラクチャの回復性
回復性は、一時的な障害から復旧する機能です。 アプリの復旧戦略では、ユーザーへの影響を最小限に抑えて通常の機能を復元します。 クラウド環境では障害が起こりうるため、アプリはダウンタイムとデータの損失が最小限になるように対応する必要があります。 問題が起きたことにユーザーが気づくことすらなく、アプリによって障害がグレースフルに処理される状況が理想的です。
マイクロサービス環境は揮発性である可能性があるため、部分的な障害を想定して処理するようにアプリを設計します。 部分的な障害の例としては、コードの例外、ネットワークの停止、応答しないサーバー プロセス、ハードウェア障害などがあります。 Kubernetes クラスター内の別のノードへのコンテナーの移動など、計画されたアクティビティも、一時的な障害の原因になる可能性があります。
回復性のアプローチ
回復性があるアプリケーションを設計する場合、その多くで、フェイル ファストするか、グレースフル デグラデーションを行うかのどちらかを選択する必要があります。 フェイル ファストは、問題が発生した場合に、問題の復旧や回避を試みるのではなく、アプリケーションがすぐにエラーまたは例外をスローすることを意味します。 これにより、問題をすばやく特定して修正できます。 グレースフル デグラデーションは、一部のコンポーネントで障害が発生した場合でも、アプリケーションが限られた容量で動作の続行を試みることを意味します。
クラウドネイティブ アプリケーションでは、フェイル ファストより、障害を適切に処理することの方が、サービスにとって重要です。 マイクロサービスは分散化されており、個別にデプロイ可能であるため、部分的な障害が予想されます。 ファイル ファストの場合、1 つのサービスで障害が発生すると依存するサービスにすぐに伝わるため、システム全体の回復性が低下します。 代わりに、内部と外部の両方のサービスの障害を予測して許容するように、マイクロサービスをコード化する必要があります。 このグレースフル デグラデーションにより、一部のサービスが中断された場合でも、システム全体の動作を継続できます。 ユーザー向けの重要な機能を維持できるため、完全な停止を回避できます。 また、グレースフルな障害の場合、システムの残りの部分に影響を与える前に、サービスの中断の発生時に復旧または自己修復することもできます。 そのため、マイクロサービスベースのアプリケーションの場合、グレースフル デグラデーションの方が、障害の分離や迅速な復旧のような回復性に関するベスト プラクティスと一致します。 これにより、ローカルなインシデントがシステム全体にカスケードされるのを防ぐことができます。
回復性によってグレースフル デグラデーションをサポートするには、アプリケーションとインフラストラクチャという 2 つの基本的なアプローチがあります。 各アプローチには、利点と欠点があります。 どちらのアプローチが適切かは状況によります。 このモジュールでは、"コード ベース" と "インフラストラクチャ ベース" の両方の回復性を実装する方法について説明します。
コード ベースの回復性
コードベースの回復性を実装するため、.NET には、回復性と一時的な障害対応のための拡張ライブラリである Microsoft.Extensions.Http.Resilience
が含まれています。
これは自然で理解しやすい構文を使って、スレッドセーフな方法でエラー処理コードを構築します。 エラー処理の動作を定義する復元ポリシーがいくつかあります。 このモジュールでは、HTTP クライアントの操作に再試行とサーキット ブレーカーの戦略を適用します。
再試行戦略
"再試行" 戦略は、その名前が意味するとおりのものです。 エラー応答を受け取った場合、短い待機の後で要求が再試行されます。 再試行を行うほど、待機時間が長くなります。 線形または指数的な増加が考えられます。
再試行の最大数に達すると、戦略は停止し、例外をスローします。 ユーザーから見ると、通常、このアプリは一部の操作を完了するのに時間がかかります。 また、このアプリは、操作を完了できなかったことをユーザーに通知する前に、しばらく時間がかかることがあります。
サーキット ブレーカー戦略
"サーキット ブレーカー" 戦略では、障害が繰り返し発生した後、ターゲット サービスとの通信を一時停止することで、中断が発生します。 サービスで重大な問題が発生しており、一時的に応答できない可能性があります。 定義された回数だけ連続して障害が発生した後、接続試行は一時停止し、回線は "開放されます"。 この待機中、ターゲット サービスに対する追加の操作は、サービスへの接続を試みることすらなく、直ちに失敗します。 待機時間が経過すると、操作が再試行されます。 サービスが問題なく応答した場合、回線は "閉じられて"、システムは通常の状態に戻ります。
インフラストラクチャ ベースの回復性
インフラストラクチャ ベースの回復性を実装するには、"サービス メッシュ" を使用できます。 コードを変更せずに回復性を確保すること以外に、サービス メッシュでは、トラフィック管理、ポリシー、セキュリティ、強力な ID、監視が提供されます。 これらの運用機能は、アプリから切り離されて、インフラストラクチャ レイヤーに移動されます。
コード ベースのアプローチとの比較
インフラストラクチャベースの回復性アプローチでは、メトリックベースのビューを使用して、リアルタイムでクラスターの状態に動的に適応することができます。 この方法では、クラスターの管理に別のディメンションが追加されますが、コードは追加されません。
コードベースのアプローチでは、以下が可能です。
- どの再試行パラメーターとタイムアウト パラメーターが適切であるかを推測する必要があります。
- 特定の HTTP 要求に注目します。
アプリのコードでインフラストラクチャの障害に対応するための適切な方法はありません。 同時に処理される数百または数千の要求を考慮することになります。 指数バックオフ (掛ける要求数) による再試行でさえ、サービスが過負荷になる可能性があります。
これに対し、インフラストラクチャベースのアプローチでは、アプリの内部構造は認識されません。 たとえば、複雑なデータベース トランザクションは、サービス メッシュには見えません。 このようなトランザクションは、コードベースのアプローチでのみ障害から保護できます。
今後のユニットでは、コード内の .NET HTTP 回復性と Linkerd サービス メッシュを使用して、マイクロサービスベースのアプリの回復性を実装します。