通过应用 Polly 策略(如重试、断路、隔离、超时和回退)即可实现这些功能。 

断路:当系统出错的次数超过了指定的阈值,就要中断当前线路,等待一段时间后再继续。

隔离:将可控的操作限制在一个固定大小的资源池中,以隔离有潜在可能相互影响的操作。

 

HttpMessageHandler 实例,该实例具有上面提到的“套接字耗尽”和 DNS 更改问题 。

它还提供基于 Polly 的中间件的扩展,以利用 HttpClient 中的委托处理程序。

使用 IHttpClientFactory 的好处

IHttpClientFactory 当前实现具有以下优势:

  • 例如,可以配置预配置的客户端(服务代理)以访问特定微服务。
  • 通过后列方式整理出站中间件的概念:在 HttpClient 中委托处理程序并实现基于 Polly 的中间件以利用 Polly 的复原策略。
  • 将 HTTP 客户端注册到工厂后,可使用一个 Polly 处理程序将 Polly 策略用于重试、断路器等。
  • HttpMessageHandler 的生存期,避免在自行管理 HttpClient 生存期时出现上述问题。

事实上,注入的 HttpClient 实例是从 DI 角度区分范围的 。

IHttpClientFactory (DefaultHttpClientFactory) 实现与 Microsoft.Extensions.DependencyInjection NuGet 包中的 DI 实现紧密关联。 

 

结合使用类型化客户端和 IHttpClientFactory

此配置可以包括特定值,如基本服务器、HTTP 标头或超时。

使用 IHttpClientFactory 实现复原 HTTP 请求

HttpMessageHandler 对象)获取自池,可供从工厂返回的 HttpClient 使用。

IHttpClientBuilder 上调用 SetHandlerLifetime(),如以下代码所示:

//Set 5 min as the lifetime for the HttpMessageHandler objects in the pool used for the Catalog Typed Client
services.AddHttpClient<ICatalogService, CatalogService>()
    .SetHandlerLifetime(TimeSpan.FromMinutes(5));

还可以在注册中添加特定于实例的配置(例如,配置基址),并添加一些弹性策略,

services.AddHttpClient<ICatalogService, CatalogService>(client =>
{
    client.BaseAddress = new Uri(Configuration["BaseUrl"]);
})
    .AddPolicyHandler(GetRetryPolicy())
    .AddPolicyHandler(GetCircuitBreakerPolicy());

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

 GetRetryPolicy 用到了Microsoft.Extensions.Http.Polly 扩展包

 

 IHttpClientFactory允许你用命名的方式来配置和使用 HttpClient。

services.AddHttpClient("GitHub", client =>
{
    client.BaseAddress = new Uri("https://api.github.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
})
.AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[]
{
    TimeSpan.FromSeconds(1),
    TimeSpan.FromSeconds(5),
    TimeSpan.FromSeconds(10)
}));

public class MyController : Controller
{
    private readonly IHttpClientFactory _httpClientFactory;

    public MyController(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public Task<IActionResult> SomeAction()
    {
        var client = _httpClientFactory.CreateClient("GitHub");
        return Ok(await client.GetStringAsync("/someapi"));
    }
}

AddTransientHttpErrorPolicy方法也可以从Polly的一个扩展包Polly.Extensions.Http中得到

 

Polly还提供了策略注册池,它相当于策略的存储中心,被注册的策略可以让你在应用程序的多个位置重用。AddPolicyHandler的一个重载方法允许您从注册池中选择策略。

var registry = services.AddPolicyRegistry();

registry.Add("defaultretrystrategy", 
    HttpPolicyExtensions.HandleTransientHttpError().WaitAndRetryAsync(/* etc */));
registry.Add("defaultcircuitbreaker", 
    HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(/* etc */));

services.AddHttpClient(/* etc */)
    .AddPolicyHandlerFromRegistry("defaultretrystrategy")
    .AddPolicyHandlerFromRegistry("defaultcircuitbreaker");

 

将抖动策略添加到重试策略

这样在出现问题时可以分散峰值。

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

 

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-03
  • 2021-10-04
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-09-06
  • 2022-12-23
  • 2021-10-04
  • 2022-01-08
  • 2022-12-23
  • 2021-06-20
  • 2021-11-11
相关资源
相似解决方案