微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法使Polly超时策略覆盖HttpClient默认超时 键入HttpClient注册政策定义延迟/罚款计算

如何解决无法使Polly超时策略覆盖HttpClient默认超时 键入HttpClient注册政策定义延迟/罚款计算

我正在使用Polly重试策略,并且在该重试过程中,预期HttpClient达到其100秒超时。我尝试了几种不同的方式来合并Polly Timeout策略,以将超时移至每次重试而不是总计,但100秒超时仍会触发。

我已经阅读了5个关于StackOverflow的问题,它们都说要包装这些策略,我什至在Polly Wiki上找到了演示,该演示说要调用AddPolicyHandler两次。那也不起作用。我确信我有一些非常基本的错误。请向我解释我的方式的错误

我正在使用.net core 5预览版7和当前的Polly nuget软件包。

键入HttpClient注册

serviceCollection.AddHttpClient<APIWrappers.SendGridClientEmail,APIWrappers.SendGridClientEmail>((c) =>
{
    c.BaseAddress = new Uri("https://api.sendgrid.com/v3a/");
})
    .AddPolicyHandler((services,req) => TransientLogAndRetry<APIWrappers.SendGridClientEmail>(services,req)
    .WrapAsync(Policy.TimeoutAsync<HttpResponseMessage>(10)));

政策定义

public IAsyncPolicy<HttpResponseMessage> TransientLogAndRetry<T>(IServiceProvider services,object req)
{
    Console.WriteLine($"Name: {typeof(T).Name} - Time: {DateTime.Now}");
    return HttpPolicyExtensions.HandleTransientHttpError().
        OrResult((rsp) => rsp.StatusCode == System.Net.HttpStatusCode.TooManyRequests).
        Or<Polly.Timeout.TimeoutRejectedException>().
        WaitAndRetryAsync(5,GetRetryTime,#pragma warning disable CS1998
            async (ex,ts,rc,ctx) =>
            {
                ((STS.Diagnostics.LoggerFactory)services.GetService<ILoggerFactory>())?.CreateLogger<T>().
                    Warn(this,"HTTP request above will retry in {0}",ts);
            }
#pragma warning restore CS1998
        );
}

延迟/罚款计算

private TimeSpan GetRetryTime(int retryCount,DelegateResult<HttpResponseMessage> response,Context context)
{
    TimeSpan result;
    long unix;

    Console.WriteLine($"Count: {retryCount} - Time: {DateTime.Now}");
    if (response.Result is null || response.Result.StatusCode != System.Net.HttpStatusCode.TooManyRequests)
        result = TimeSpan.FromSeconds(Math.Min(Math.Pow(Math.Sqrt(retryCount * 2),5),60 * 60));
    else
    {
        unix = response.Result.Headers.GetValues("X-RateLimit-Reset").Select((v) => long.Parse(v)).First();
        result = DateTime.UtcNow - DateTimeOffset.FromUnixTimeSeconds(unix);
    }
    Console.WriteLine(result);
    return result;
}

解决方法

根据提供的代码,我可以看到以下弹性策略:

100秒全局超时

5次重试(= 5 + 1次尝试)

指数退避逻辑

10秒本地超时


如果我正确理解了您的问题,那么您正在寻找增加全局超时的解决方案。

最简单的解决方案(1)是将HttpClient实例的Timeout属性从默认值100增加到所需值。如果超过此超时时间,则实例将抛出OperationCanceledException,并且无法建立进一步的重试尝试。

如果HttpClient实例在不同组件之间共享/重用,则可能需要更改每次使用的全局超时。您可以通过在HttpClient的全局超时和您的重试策略之间引入新的超时策略来克服这一问题。

因此,您可能会进行以下设置:

200秒的全局超时(通过HttpClient

150秒整体/总体超时(根据外部超时策略)

5次重试(= 5 + 1次尝试)

指数退避逻辑

10秒本地超时

在这种情况下,我建议像这样使用Policy.WrapAsync1):

Policy.WrapAsync(OverallTimeoutPolicy(),RetryPolicy(),LocalTimeoutPolicy());

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。