IHttpClientFactory ポリシーと Polly ポリシーで指数バックオフを含む HTTP 呼び出しの再試行を実装するImplement HTTP call retries with exponential backoff with IHttpClientFactory and Polly policies

指数のバックオフでの再試行のためのアプローチとしては、オープン ソースである Polly ライブラリのような高度な .NET ライブラリを利用することをお勧めします。The recommended approach for retries with exponential backoff is to take advantage of more advanced .NET libraries like the open-source Polly library.

Polly とは、回復機能と一時的な障害処理の機能を提供する .NET ライブラリです。Polly is a .NET library that provides resilience and transient-fault handling capabilities. このような機能は、再試行、遮断器、バルクヘッド分離、タイムアウト、フォールバックなどの Polly ポリシーを適用することで実装できます。You can implement those capabilities by applying Polly policies such as Retry, Circuit Breaker, Bulkhead Isolation, Timeout, and Fallback. Polly は .NET Framework 4.x と .NET Standard 1.0、1.1、および 2.0 (.NET Core をサポート) を対象としています。Polly targets .NET Framework 4.x and .NET Standard 1.0, 1.1, and 2.0 (which supports .NET Core).

次の手順では、前のセクションで説明した、IHttpClientFactory に統合された Polly で HTTP 再試行を使用する方法を示します。The following steps show how you can use Http retries with Polly integrated into IHttpClientFactory, which is explained in the previous section.

ASP.NET Core 3.1 パッケージを参照するReference the ASP.NET Core 3.1 packages

IHttpClientFactory は .NET Core 2.1 以降で使用できますが、最新の ASP.NET Core 3.1 パッケージを NuGet から入手し、プロジェクトで使用することをお勧めします。IHttpClientFactory is available since .NET Core 2.1 however we recommend you to use the latest ASP.NET Core 3.1 packages from NuGet in your project. また、通常は Microsoft.Extensions.Http.Polly 拡張機能パッケージを参照する必要もあります。You typically also need to reference the extension package Microsoft.Extensions.Http.Polly.

Startup で、Polly の再試行ポリシーでクライアントを構成するConfigure a client with Polly's Retry policy, in Startup

前のセクションで示したように、標準の Startup.ConfigureServices(...) メソッドで、名前または型が指定された HttpClient 構成を定義する必要がありますが、今後は以下のように、指数バックオフを含む HTTP 再試行のポリシーを指定し、増分コードを追加します。As shown in previous sections, you need to define a named or typed client HttpClient configuration in your standard Startup.ConfigureServices(...) method, but now, you add incremental code specifying the policy for the Http retries with exponential backoff, as below:

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

AddPolicyHandler() メソッドは、使用する HttpClient オブジェクトにポリシーを追加します。The AddPolicyHandler() method is what adds policies to the HttpClient objects you'll use. この場合、指数バックオフを含む HTTP 再試行に対して Polly のポリシーが追加されます。In this case, it's adding a Polly's policy for Http Retries with exponential backoff.

手法のモジュール性を高めるために、次のコードで示すように、Startup.cs ファイル内の個別メソッドに HTTP 再試行ポリシーを定義できます。To have a more modular approach, the Http Retry Policy can be defined in a separate method within the Startup.cs file, as shown in the following code:

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 例外が発生した場合に実行するアクション (エラーの記録など) を定義できます。With Polly, you can define a Retry policy with the number of retries, the exponential backoff configuration, and the actions to take when there's an HTTP exception, such as logging the error. 上記のコードでは、指数関数的再試行で (最初は 2 秒) 6 回試すようにポリシーが構成されています。In this case, the policy is configured to try six times with an exponential retry, starting at two seconds.

再試行ポリシーにジッタ方式を追加するAdd a jitter strategy to the retry policy

通常の再試行ポリシーは、コンカレンシーやスケーラビリティが高い場合や、高競合状態下でシステムに影響を及ぼすことがあります。A regular Retry policy can impact your system in cases of high concurrency and scalability and under high contention. 部分的な停止の場合に多くのクライアントから来る同様の再試行のピークを乗り越えるための賢い回避策は、ジッタ方式を再試行アルゴリズムまたはポリシーに追加することです。To overcome peaks of similar retries coming from many clients in case of partial outages, a good workaround is to add a jitter strategy to the retry algorithm/policy. これにより、急増するバックオフにランダム性を加えることで、エンドツーエンド システム全体のパフォーマンスを向上できます。This can improve the overall performance of the end-to-end system by adding randomness to the exponential backoff. こうすれば、問題が発生した際のスパイクを分散できます。This spreads out the spikes when issues arise. この原則を次の例で示します。The principle is illustrated by the following example:

Random jitterer = new Random();
var retryWithJitterPolicy = HttpPolicyExtensions
    .HandleTransientHttpError()
    .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
    .WaitAndRetryAsync(6,    // exponential back-off plus some jitter
        retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))  
                      + TimeSpan.FromMilliseconds(jitterer.Next(0, 100))
    );

Polly はプロジェクトの Web サイトを通じて、実稼働可能なジッタ アルゴリズムを提供します。Polly provides production-ready jitter algorithms via the project website.

その他の技術情報Additional resources