回復性は、アプリが一時的な障害から回復し、引き続き機能する機能です。 .NET プログラミングのコンテキストでは、障害を適切に処理し、迅速に回復できるアプリを設計することで回復性が実現されます。 .NET で回復性のあるアプリを構築するために、NuGet では次の 2 つのパッケージを利用できます。
NuGet パッケージ | 説明 |
---|---|
📦 Microsoft.Extensions.Resilience | この NuGet パッケージは、一時的な障害に対してアプリを強化するメカニズムを提供します。 |
📦 Microsoft.Extensions.Http.Resilience | この NuGet パッケージは、 HttpClient クラス専用の回復性メカニズムを提供します。 |
これら 2 つの NuGet パッケージは、人気のあるオープンソース プロジェクトである Polly の上に構築されています。 Polly は、 再試行、 サーキット ブレーカー、タイムアウト、 バルクヘッドの分離、 レート制限、フォールバック、ヘッジなどの戦略を、開発者が流暢でスレッド セーフな方法で表現できる .NET の回復性と一時的な障害処理ライブラリです。
Von Bedeutung
Microsoft.Extensions.Http.Polly NuGet パッケージは非推奨です。 代わりに、前述のパッケージのいずれかを使用してください。
始めましょう
.NET で回復性の使用を開始するには、 Microsoft.Extensions.Resilience NuGet パッケージをインストールします。
dotnet add package Microsoft.Extensions.Resilience --version 8.0.0
詳細については、「.NET アプリケーションでの dotnet パッケージの追加 または パッケージの依存関係の管理」を参照してください。
回復性パイプラインを構築する
回復性を使用するには、まず回復性ベースの戦略のパイプラインを構築する必要があります。 構成された各戦略は、構成の順序で実行されます。 言い換えると、順序は重要です。 エントリ ポイントは、IServiceCollectionという名前のAddResiliencePipeline
型の拡張メソッドです。 このメソッドは、パイプラインの識別子と、パイプラインを構成するデリゲートを受け取ります。 デリゲートには、パイプラインに回復性戦略を追加するために使用される ResiliencePipelineBuilder
のインスタンスが渡されます。
次の文字列ベースの key
例を考えてみます。
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.CircuitBreaker;
using Polly.Registry;
using Polly.Retry;
using Polly.Timeout;
var services = new ServiceCollection();
const string key = "Retry-Timeout";
services.AddResiliencePipeline(key, static builder =>
{
// See: https://www.pollydocs.org/strategies/retry.html
builder.AddRetry(new RetryStrategyOptions
{
ShouldHandle = new PredicateBuilder().Handle<TimeoutRejectedException>()
});
// See: https://www.pollydocs.org/strategies/timeout.html
builder.AddTimeout(TimeSpan.FromSeconds(1.5));
});
前述のコード:
- 新しい
ServiceCollection
インスタンスを作成します。 - パイプラインを識別する
key
を定義します。 ServiceCollection
インスタンスに回復性パイプラインを追加します。- 再試行とタイムアウトの戦略を使用してパイプラインを構成します。
各パイプラインは特定の key
用に構成され、各 key
は、プロバイダーからパイプラインを取得するときに対応する ResiliencePipeline
を識別するために使用されます。 key
は、AddResiliencePipeline
メソッドのジェネリック型パラメーターです。
レジリエンスパイプラインビルダー拡張機能
パイプラインに戦略を追加するには、Add*
インスタンスで使用可能なResiliencePipelineBuilder
拡張メソッドのいずれかを呼び出します。
AddRetry
: 何かが失敗した場合は、もう一度やり直してください。これは、問題が一時的であり、消える可能性がある場合に役立ちます。AddCircuitBreaker
:何かが壊れているか、忙しい場合は試してみるのをやめてください。無駄な時間を避け、物事を悪化させることでメリットがあります。AddTimeout
: 時間がかかりすぎる場合は、諦めることでリソースを解放し、パフォーマンスを向上させることができます。AddRateLimiter
: 受け入れる要求の数を制限します。これにより、受信負荷を制御できます。AddConcurrencyLimiter
: 送信負荷を制御できる要求の数を制限します。AddFallback
: エラーが発生したときに他の操作を行うと、ユーザー エクスペリエンスが向上します。AddHedging
: 待機時間が長い場合やエラーが発生した場合に複数の要求を発行すると、応答性が向上する可能性があります。
詳細については、「 回復性戦略」を参照してください。 例については、「 回復性のある HTTP アプリの構築: 主要な開発パターン」を参照してください。
指標の拡充
エンリッチメント は、名前と値のペアの形式で、既知の状態を持つテレメトリの自動拡張です。 たとえば、アプリは、操作の結果を表す 列として操作 と 結果コード を含むログを出力する場合があります。 このような状況では、周辺機器のコンテキストに応じて、エンリッチメントによって、テレメトリ バックエンドに送信されるクラスター 名、 プロセス名、 リージョン、 テナント ID などがログに追加されます。 エンリッチメントが追加されると、強化されたメトリックの恩恵を受けるために、アプリ コードで追加の操作を行う必要はありません。
エンリッチメントのしくみ
ログとメトリックを生成するグローバル分散サービス インスタンスが 1,000 個あるとします。 サービス ダッシュボードで問題が発生した場合は、問題のあるリージョンまたはデータ センターをすばやく特定することが重要です。 エンリッチメントにより、分散システムの障害を特定するために必要な情報がメトリック レコードに含まれるようにします。 エンリッチメントがない場合、アプリのコードがこの状態を管理し、ログプロセスに統合して手動で送信する責任を負わなければなりません。 エンリッチメントにより、このプロセスが簡略化され、アプリのロジックに影響を与えることなくシームレスに処理できます。
回復性の場合、エンリッチメントを追加すると、次のディメンションが送信テレメトリに追加されます。
error.type
: 例外情報の低カーディナリティバージョン。request.name
: 要求の名前。request.dependency.name
: 依存関係の名前。
内部的には、回復性エンリッチメントは Polly のテレメトリ MeteringEnricher
に基づいて構築されています。 詳細については、「Polly: 測定エンリッチメント」を参照してください。
レジリエンスエンリッチメントを追加する
回復性パイプラインを登録するだけでなく、回復性エンリッチメントを登録することもできます。 エンリッチメントを追加するには、AddResilienceEnricher(IServiceCollection) インスタンスで IServiceCollection
extensions メソッドを呼び出します。
services.AddResilienceEnricher();
AddResilienceEnricher
拡張メソッドを呼び出すことで、基になる Polly ライブラリに組み込まれている既定のディメンションの上にディメンションを追加します。 次のエンリッチメント ディメンションが追加されます。
- IExceptionSummarizerに基づく例外エンリッチメント。テレメトリで使用する例外を要約するメカニズムを提供します。 詳細については、 例外の要約を参照してください。
- テレメトリの要求メタデータを保持するRequestMetadataに基づいて、メタデータのエンリッチメントを要求してください。 詳細については、「 Polly: Telemetry metrics」を参照してください。
回復性パイプラインを使用する
構成された回復性パイプラインを使用するには、 ResiliencePipelineProvider<TKey>
からパイプラインを取得する必要があります。 前にパイプラインを追加したとき、 key
は string
型であるため、 ResiliencePipelineProvider<string>
からパイプラインを取得する必要があります。
using ServiceProvider provider = services.BuildServiceProvider();
ResiliencePipelineProvider<string> pipelineProvider =
provider.GetRequiredService<ResiliencePipelineProvider<string>>();
ResiliencePipeline pipeline = pipelineProvider.GetPipeline(key);
前述のコード:
ServiceProvider
インスタンスからServiceCollection
をビルドします。- サービス プロバイダーから
ResiliencePipelineProvider<string>
を取得します。 ResiliencePipeline
からResiliencePipelineProvider<string>
を取得します。
回復性パイプラインを実行する
回復性パイプラインを使用するには、Execute*
インスタンスで使用可能なResiliencePipeline
メソッドのいずれかを呼び出します。 たとえば、 ExecuteAsync
メソッドの呼び出しの例を考えてみましょう。
await pipeline.ExecuteAsync(static cancellationToken =>
{
// Code that could potentially fail.
return ValueTask.CompletedTask;
});
上記のコードは、 ExecuteAsync
メソッド内でデリゲートを実行します。 エラーが発生すると、構成された戦略が実行されます。 たとえば、 RetryStrategy
が 3 回再試行するように構成されている場合、失敗が反映される前に、デリゲートが 4 回 (1 回の最初の試行と 3 回の再試行) 実行されます。
次のステップ
.NET