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

DotNetCore实战

共 3046字,需浏览 7分钟

 ·

2021-01-21 07:50


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

Intro

我们的服务里有一个 API 会去调用第三方的接口,设置了超时时间,最近偶尔会发生超时的情况,微软在提供 HttpClientFactory 的同时,也提供了一个基于 Polly 的一个扩展,我们可以借助它轻松地实现重试,熔断等行为。

Sample

使用 Polly 扩展需要引用 nuget 包 :Microsoft.Extensions.Http.Polly

使用示例:

services.AddHttpClient(ServiceConst.IterableHttpClientName, x =>
{
    x.Timeout = new TimeSpan(003);
})
    .AddTransientHttpErrorPolicy(builder =>
    {
        return builder.Or()
            .Or()
            .Or()
            .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()
                    .Or()
                    .Or()
                    .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()
            .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 _getResponseFunc;

    public MockHttpHandler(Func getResponseFunc)
    {
        _getResponseFunc = getResponseFunc;
    }

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

More

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

Reference

  • https://www.nuget.org/packages/Microsoft.Extensions.Http.Polly
  • https://github.com/dotnet/aspnetcore/tree/master/src/HttpClientFactory/Polly/src



往期精彩回顾




【推荐】.NET Core开发实战视频课程 ★★★

.NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划

【.NET Core微服务实战-统一身份认证】开篇及目录索引

Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南)

.NET Core中的一个接口多种实现的依赖注入与动态选择看这篇就够了

10个小技巧助您写出高性能的ASP.NET Core代码

用abp vNext快速开发Quartz.NET定时任务管理界面

在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度

现身说法:实际业务出发分析百亿数据量下的多表查询优化

关于C#异步编程你应该了解的几点建议

C#异步编程看这篇就够了


浏览 25
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报