使用 IHttpClientFactory 和 Polly 策略实现指数回退的 HTTP 调用重试

小窍门

此内容摘自电子书《适用于容器化 .NET 应用程序的 .NET 微服务体系结构》,可以在 .NET Docs 上获取,也可以下载免费的 PDF 以供离线阅读。

适用于容器化 .NET 应用程序的 .NET 微服务体系结构电子书封面缩略图。

建议的使用指数退避算法的重试方法是利用更高级的 .NET 库,如开放源 Polly 库。

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 起可用,但建议在项目中使用 NuGet 中的最新 .NET 8 包。 通常还需要引用扩展包 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)));
}

如前面的部分所示,需要在标准 Program.cs 应用配置中定义命名或类型化的客户端 HttpClient 配置。 现在,增加代码,指定使用指数退避策略进行 Http 重试,如下所示:

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

使用 Polly,可以定义重试策略,其中包含重试次数、指数退避配置,以及在出现 HTTP 异常时要执行的作,例如记录错误。 在这种情况下,策略配置为尝试六次,采用指数重试机制,从两秒开始。

在重试策略中添加一个抖动机制

在高并发率、高可伸缩性和高争用的情况下,常规重试策略可能会对系统产生影响。 在部分运行中断时,可能会有许多客户端同时发出相似的重试操作,从而形成操作高峰,为避免这种情况,一个好办法是向重试算法或策略中添加抖动策略。 此策略可以提高端到端系统的整体性能。 如 Polly:重试与抖动中所建议,一个好的抖动策略可以通过采用均匀分布的平滑重试间隔并在指数退避上应用一个控制良好的中值初始重试延迟来实现。 此方法有助于在出现问题时分散峰值。 该原则由以下示例说明:


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

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

其他资源