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

ヒント

このコンテンツは eBook の「コンテナー化された .NET アプリケーションの .NET マイクロサービス アーキテクチャ」からの抜粋です。.NET Docs で閲覧できるほか、PDF として無料ダウンロードすると、オンラインで閲覧できます。

.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 パッケージをインストールする

まず、Microsoft.Extensions.Http.Polly パッケージをインストールする必要があります。

.NET 8 パッケージの参照

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

アプリの起動時に Polly の再試行ポリシーでクライアントを構成する

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

手法のモジュール性を高めるには、次のコードで示すように、Program.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)));
}

前のセクションで示したように、名前付きまたは型指定されたクライアント HttpClient 構成を標準の Program.cs アプリ構成内に定義する必要があります。 ここで、次のように、エクスポネンシャル バックオフを使った Http 再試行のポリシーを指定して増分コードを追加します。

// Program.cs
builder.Services.AddHttpClient<IBasketService, BasketService>()
        .SetHandlerLifetime(TimeSpan.FromMinutes(5))  //Set lifetime to five minutes
        .AddPolicyHandler(GetRetryPolicy());

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);

その他の技術情報