IHttpClientFactory ポリシーと Polly ポリシーで指数バックオフを含む HTTP 呼び出しの再試行を実装する

ヒント

このコンテンツは、.NET Docs で入手できる、またはオフラインで読み取ることができる無料のダウンロード可能な PDF として入手できる、コンテナー化された .NET アプリケーション用の電子ブックである .NET マイクロサービス アーキテクチャからの抜粋です。

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

指数のバックオフでの再試行のためのアプローチとしては、オープン ソースである Polly ライブラリのような高度な .NET ライブラリを利用することをお勧めします。

Polly とは、回復機能と一時的な障害処理の機能を提供する .NET ライブラリです。 このような機能は、再試行、遮断器、バルクヘッド分離、タイムアウト、フォールバックなどの Polly ポリシーを適用することで実装できます。 Polly は .NET Framework 4.x と .NET Standard 1.0、1.1、および 2.0 (.NET Core 以降をサポート) を対象としています。

次の手順では、前のセクションで説明した、IHttpClientFactory に統合された Polly で HTTP 再試行を使用する方法を示します。

.NET 6 パッケージの参照

IHttpClientFactoryは .NET Core 2.1 以降で使用できますが、プロジェクトでNuGetの最新の .NET 6 パッケージを使用することをお勧めします。 また、通常は Microsoft.Extensions.Http.Polly 拡張機能パッケージを参照する必要もあります。

Startup で、Polly の再試行ポリシーでクライアントを構成する

前のセクションで示したように、標準 Startup.ConfigureServices(...) メソッドで名前付きまたは型指定されたクライアント HttpClient 構成を定義する必要がありますが、次に示すように、指数バックオフによる Http 再試行のポリシーを指定する増分コードを追加します。

//ConfigureServices()  - Startup.cs
services.AddHttpClient<IBasketService, BasketService>()
        .SetHandlerLifetime(TimeSpan.FromMinutes(5))  //Set lifetime to five minutes
        .AddPolicyHandler(GetRetryPolicy());

AddPolicyHandler() メソッドは、使用する HttpClient オブジェクトにポリシーを追加します。 この場合、指数バックオフを含む HTTP 再試行に対して Polly のポリシーが追加されます。

手法のモジュール性を高めるために、次のコードで示すように、Startup.cs ファイル内の個別メソッドに HTTP 再試行ポリシーを定義できます。

static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
        .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2,
                                                                    retryAttempt)));
}

Polly では、再試行回数を指定した再試行ポリシー、指数バックオフの構成、HTTP 例外が発生した場合に実行するアクション (エラーの記録など) を定義できます。 上記のコードでは、指数関数的再試行で (最初は 2 秒) 6 回試すようにポリシーが構成されています。

再試行ポリシーにジッタ方式を追加する

通常の再試行ポリシーは、コンカレンシーやスケーラビリティが高い場合や、高競合状態下でシステムに影響を及ぼすことがあります。 部分的な停止で多くのクライアントから来る同様の再試行のピークを乗り越えるための賢い回避策は、ジッタ方式を再試行アルゴリズムまたはポリシーに追加することです。 この戦略により、エンドツーエンド システムの全体的なパフォーマンスを向上させることができます。 Polly: Retry with Jitter (ジッタで再試行) で推奨されているように、指数バックオフでの初期再試行遅延の中央値を適切に制御して、スムーズで均等に分散された再試行間隔を適用することで、優れたジッタ戦略を実施できます。 この方法は、問題が発生したときにスパイクを分散させることができます。 この原則を次の例で示します。


var delay = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(1), retryCount: 5);

var retryPolicy = Policy
    .Handle<FooException>()
    .WaitAndRetryAsync(delay);

その他の技術情報