您的位置:首页 > 理论基础 > 计算机网络

HttpClientFactory 结合 Polly 轻松实现重试机制

2021-01-15 23:56 1256 查看

HttpClientFactory 结合 Polly 轻松实现重试机制

Intro

我们的服务里有一个 API 会去调用第三方的接口,设置了超时时间,最近偶尔会发生超时的情况,微软在提供

HttpClientFactory
的同时,也提供了一个基于
Polly
的一个扩展,我们可以借助它轻松地实现重试,熔断等行为。

Sample

使用 Polly 扩展需要引用 nuget 包 :

Microsoft.Extensions.Http.Polly

使用示例:

services.AddHttpClient(ServiceConst.IterableHttpClientName, x =>
{
x.Timeout = new TimeSpan(0, 0, 3);
})
.AddTransientHttpErrorPolicy(builder =>
{
return builder.Or<TaskCanceledException>()
.Or<OperationCanceledException>()
.Or<TimeoutException>()
.OrResult(res => res.StatusCode == HttpStatusCode.TooManyRequests || (int)res.StatusCode >= 500)
.RetryAsync(5)
;
})

通过

AddTransientHttpErrorPolicy
扩展方法来注册一个 Polly 的 policy,具体可以通过
policyBuilder
委托来定制自己要处理的情况和 policy 行为,支持方式有很多可以简单的指定重试,也可以指定
WaitANdRetryAsync
等待一段时间后重试,可以重试一次也可以一直重试下去,非常的灵活,可以根据自己的业务场景进行定制化配置,这里的示例直接是用了简单的重试机制

单元测试

下面提供了一个测试重试的单元测试,也可以作为使用示例的一个参考:

[Fact]
public async Task TaskCanceledException()
{
var ticks = new ConcurrentBag<long>();
var retryLimit = 5;

var services = new ServiceCollection();
services.AddHttpClient("test", x =>
{
x.Timeout = TimeSpan.FromSeconds(1);
})
.AddTransientHttpErrorPolicy(builder =>
{
return builder.Or<TaskCanceledException>()
.Or<OperationCanceledException>()
.Or<TimeoutException>()
.OrResult(res =>
res.StatusCode == HttpStatusCode.TooManyRequests || (int)res.StatusCode >= 500)
.RetryAsync(retryLimit)
;
})
.AddHttpMessageHandler(() => new MockHttpHandler(request =>
{
ticks.Add(DateTime.UtcNow.Ticks);
throw new TaskCanceledException();
}))

;
await using var provider = services.BuildServiceProvider();
try
{
using var response = await provider.GetRequiredService<IHttpClientFactory>()
.CreateClient("test")
.GetAsync("api/test");
}
catch (Exception e)
{
Assert.True(e is OperationCanceledException);
}
Assert.Equal(retryLimit + 1, ticks.Count);
}

private class MockHttpHandler : DelegatingHandler
{
private readonly Func<HttpRequestMessage, HttpResponseMessage> _getResponseFunc;

public MockHttpHandler(Func<HttpRequestMessage, HttpResponseMessage> getResponseFunc)
{
_getResponseFunc = getResponseFunc;
}

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult(_getResponseFunc(request));
}
}

More

除了

AddTransientHttpErrorPolicy
之外,Polly 扩展还支持
AddPolicyHandler
/
AddPolicyHandlerFromRegistry
扩展方法,有兴趣的可以自己探索一下哈~~

Reference

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: