• 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

  • 相关阅读:
    1582. Special Positions in a Binary Matrix
    623. Add One Row to Tree
    617. Merge Two Binary Trees
    643. Maximum Average Subarray I
    645. Set Mismatch
    1022. Sum of Root To Leaf Binary Numbers
    835. Image Overlap
    HDU Marriage is Stable (稳定婚姻匹配)
    HDU Stable Match (稳定婚姻匹配)
    HDU Maximum Clique (最大团)
  • 原文地址:https://www.cnblogs.com/weihanli/p/httpclientfactory-polly.html
Copyright © 2020-2023  润新知