HttpClientFactory 是 .NET CORE 2.1 中新增加的功能,目的是为了解决直接使用 HttpClient 可能带来的一系列问题(优雅通过 HttpClientFactory 使用 HttpClient),本文主要介绍 HttpClientFactory 整合 Polly 的使用,实现对 Http 请求的超时、重试、熔断、降级等操作。
HttpClientFactory 集成 Polly
创建 .NET Core API 项目(这里使用的是 .NET Core 2.2);
安装
Microsoft.Extensions.Http.PollyNuGet Package;在 Startup.cs 的 ConfigureServices 方法中添加 HttpClient 相关代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45public void ConfigureServices(IServiceCollection services)
{
var fallbackResponse = new HttpResponseMessage
{
Content = new StringContent("Fallback"),
StatusCode = HttpStatusCode.GatewayTimeout
};
services.AddHttpClient("github", client =>
{
client.BaseAddress = new Uri("https://www.github.com");
})
// 降级
.AddPolicyHandler(Policy<HttpResponseMessage>.Handle<Exception>().FallbackAsync(fallbackResponse, async b =>
{
await Task.CompletedTask;
_logger.LogWarning($"Fallback: {b.Exception.Message}");
}))
// 熔断
.AddPolicyHandler(Policy<HttpResponseMessage>.Handle<TimeoutRejectedException>().CircuitBreakerAsync(5, TimeSpan.FromSeconds(3), (ex, ts) =>
{
_logger.LogWarning($"Open Circuit Breaker:{ts.TotalMilliseconds}");
}, () =>
{
_logger.LogWarning($"Closed Circuit Breaker");
}, () =>
{
_logger.LogWarning($"HalfOpen Circuit Breaker");
}))
// 重试
.AddPolicyHandler(Policy<HttpResponseMessage>
.Handle<TimeoutRejectedException>()
.WaitAndRetryAsync(
new[]
{
TimeSpan.FromMilliseconds(100),
TimeSpan.FromMilliseconds(200)
}
)
)
// 超时
.AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(0.5)));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}说明(这部分代码在实际使用中建议重新封装,不应该每次都为当前定义的
HttpClient设置一堆重复代码):- 通过
services.AddHttpClient定义一个名为github的HttpClient,后续可通过名称获取到这个 HttpClient 对象来发送 Http 请求; - 通过
AddPolicyHandler(其他扩展方法参考:Polly and HttpClientFactoryAddTransientHttpErrorPolicy、AddPolicyHandlerFromRegistry的使用介绍) 为此HttpClient添加Polly策略; - 设置降级策略,当出现任何异常,返回
fallbackResponse; - 设置熔断策略,当连续出现
TimeoutRejectedException异常 5 次,熔断 3s; - 设置重试策略,当出现
TimeoutRejectedException分别等待 100ms、200ms 后重试; - 设置超时策略,请求超时为 0.5s,超时默认会抛出
TimeoutRejectedException; - 当多个策略叠加时,最先起作用的是最后添加的;
- 通过
使用 HttpClient
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class ValuesController : ControllerBase
{
private readonly IHttpClientFactory _httpClientFactory;
public ValuesController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public async Task<ActionResult> Get()
{
var client = _httpClientFactory.CreateClient("github");
var request = new HttpRequestMessage(HttpMethod.Get, "/");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
return Ok(result);
}
}说明:从
HttpClientFactory中获取定义好的名为github的HttpClient对象,和普通的HttpClient的区别是此HttpClient已具有定义的各种Polly策略,其他没任何区别;效果测试
Timeout Retry

Timeout Circuit Breaker



Fallback
