.NET Core:使用 HttpClientFactory 和 Polly 构建坚如磐石的服务
让我们从IHttpClientFactory
波莉
在这篇文章中,我将解释什么是 HttpClientFactory 和 Polly 重试策略以及为什么应该在下一个项目中使用它们。
让我们从IHttpClientFactory
很多客户打电话给我,希望我帮助他们解决突发和随机请求失败的问题。他们将一项新服务投入生产,最初几天运行良好,但突然之间,他们在Application Insights中看到大量SocketException异常。
大多数情况下,这些失败是由于错误使用 HttpClient而导致套接字耗尽。
HttpClient 的设计初衷是实例化一次,并在应用程序的整个生命周期内重复使用。如果每次请求都实例化一个HttpClient类,在高负载下会耗尽可用的套接字数量。
因此请避免使用如下代码:
using (var httpClient = new HttpClient())
{
var result = await httpClient.GetAsync("https://www.bing.com");
}
您可以在此处阅读有关此问题的更多详细信息:
https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
因此,为了缓解这个问题,.NET Core 团队在 .NET Core 2.1 中引入了IHttpClientFactory,它提供了以下好处:
-
提供命名和配置逻辑 HttpClient 对象的中心位置。例如,你可以配置一个预先配置为访问特定微服务的客户端(服务代理)。
-
通过在 HttpClient 中委托处理程序并实现基于 Polly 的中间件来编纂传出中间件的概念,以利用 Polly 的弹性策略。
-
HttpClient 已经提供了委托处理程序的概念,这些处理程序可以链接在一起以处理传出的 HTTP 请求。您可以将 HTTP 客户端注册到工厂中,并使用 Polly 处理程序来使用 Polly 策略进行重试、断路器等操作。
-
管理 HttpMessageHandler 的生命周期以避免自己管理 HttpClient 生命周期时可能发生的上述问题。
让我们看一个利用 IHttpClientFactory 的简单示例。
在我的示例中,我将使用一个非常酷炫且免费的 API—— SuperHero (你可以在https://apilist.fun/找到更多免费 API 来试用)。
在新的 Web API 项目中,按照如下方式Startup.cs
更改ConfigureServices
方法:
public void ConfigureServices(IServiceCollection services)
{
// the AddHttpClient() will provide us with an instance of HttpClient
// available for Dependancy Injection in our services
services.AddHttpClient<ISuperHeroService, SuperHeroService>(o =>
o.BaseAddress = new Uri(Configuration["SuperHeroApiConfig:BaseUrl"]));
services.AddControllers();
}
现在让我们创建我们的SuperHeroService
:
public class SuperHeroService : ISuperHeroService
{
private readonly HttpClient _httpClient;
private readonly ISuperHeroApiConfig _superHeroApiConfig;
public SuperHeroService(HttpClient httpClient, ISuperHeroApiConfig superHeroApiConfig)
{
_httpClient = httpClient;
_superHeroApiConfig = superHeroApiConfig;
}
public async Task<PowerStats> GetPowerStats(int id)
{
return await _httpClient.GetFromJsonAsync<PowerStats>(
$"{_superHeroApiConfig.AccessToken}/{id}/powerstats");
}
}
最后但同样重要的是让我们创建我们的SuperHeroController
:
[ApiController]
[Route("api/[controller]")]
public class SuperHeroController : ControllerBase
{
private readonly ILogger<SuperHeroController> _logger;
private readonly ISuperHeroService _superHeroService;
public SuperHeroController(ILogger<SuperHeroController> logger, ISuperHeroService superHeroService)
{
_logger = logger;
_superHeroService = superHeroService;
}
[HttpGet("GetPowerStats/{id}")]
public async Task<ActionResult> GetPowerStats(int id)
{
var result = await _superHeroService.GetPowerStats(id);
return Ok(result);
}
}
您可以使用 Postman 或任何其他应用程序来测试您的 Super Hero 服务:
现在我们看到了使用 克服旧的 HttpClient 问题是多么容易IHttpClientFactory
,让我们使用Polly让我们的 Super Hero 服务更能抵御故障。
波莉
Polly 是一个 .NET 弹性和瞬态故障处理库,允许开发人员以流畅且线程安全的方式表达重试、断路器、超时、舱壁隔离和回退等策略。
我想我们大多数人在某个时间点都看到过这样的代码,试图实现某种重试逻辑。
public async Task<PowerStats> GetPowerStats(int id)
{
var currentRetry = 0;
while (true)
{
try
{
return await _httpClient.GetFromJsonAsync<PowerStats>(
$"{_superHeroApiConfig.AccessToken}/{id}/powerstats");
}
catch (Exception ex)
{
currentRetry++;
if (currentRetry > 3)
{
throw;
}
}
}
}
然而,我们都同意这种方法并不干净且易于维护,特别是在具有许多不同服务和端点的大型项目中。
Polly
来救援!
步骤1:添加Polly nuget包Microsoft.Extensions.Http.Polly
。
第 2 步:ConfigureServices
在方法中创建自定义策略Startup.cs
。
// Create the retry policy we want
var retryPolicy = HttpPolicyExtensions
.HandleTransientHttpError() // HttpRequestException, 5XX and 408
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(retryAttempt));
步骤 3:将其应用到我们的 SuperHeroService,非常简单!
services.AddHttpClient<ISuperHeroService, SuperHeroService>(o =>
o.BaseAddress = new Uri(Configuration["SuperHeroApiConfig:BaseUrl"]))
.AddPolicyHandler(retryPolicy);
那么当我们的 SuperHeroService 收到TransientHttpError
(HttpRequestException, 5XX, 408) 时会发生什么?
我们的HttpClient会重试请求。
第一次重试会等待 1 秒后重试。
第二次重试会等待 2 秒后重试。
第三次也是最后一次重试会等待 3 秒后重试。
如果再次失败,则不会重试,直接返回。
这是一个非常简单的示例,仅用于演示基本Polly
用法,但您可以做更多的事情。
您可以根据需要定制重试策略,只需几行代码即可应用断路器、超时、隔墙隔离和回退。
现在您已经掌握了构建坚如磐石的服务的知识,请使用它!
你可以在我的GitHub上找到完整的代码
这篇文章充满爱意❤️
鏂囩珷鏉ユ簮锛�https://dev.to/rickystam/net-core-use-httpclientfactory-and-polly-to-build-rock-solid-services-2edh