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


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

    Intro

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

    Sample

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

    使用示例:

    services.AddHttpClient("test", x =>
    {
        x.Timeout = new TimeSpan(0, 0, 3);
    })
        .AddTransientHttpErrorPolicy(builder =>
        {
            return builder.Or<TaskCanceledException>()
                .Or<OperationCanceledException>()
                .Or<TimeoutException>()
                .OrResult(res => res.StatusCode == HttpStatusCode.TooManyRequests)
                .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)
                        .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

  • 相关阅读:
    好记性不如烂笔头,要经常把学习的东西记录下来
    liunx git 已经设置了ssh key 还是需要帐号和密码的解决方法。
    解决composer ssl required for SSL/TLS 证书配置
    composer SSL: Handshake timed out 解决办法
    小程序解密报错:IV passed is 24 bytes long which is longer than the 16 expected by se
    PHP面向对象试题(基础部分)
    php 单例模式
    在Thinkphp里面加入验证码插件
    phpstorm 修改默认注释
    用PHP去掉文件头的Unicode签名(BOM)
  • 原文地址:https://www.cnblogs.com/weihanli/p/httpclientfactory-polly.html
Copyright © 2020-2023  润新知