1

我正在使用 Polly 重试策略,并且正如预期的那样,在重试过程中,HttpClient它的超时时间达到了 100 秒。我尝试了几种不同的方法来合并 Polly Timeout 策略以将超时移动到每次重试而不是总计,但是 100 秒超时一直触发。

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

我正在使用 .net core 5 preview 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;
}
4

1 回答 1

2

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

100 秒全局超时

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

指数回退逻辑

10 秒本地超时


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

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

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

因此,您最终可能会得到以下设置:

200 秒全局超时(通过 HttpClient

150 秒整体/总体超时(通过外部超时策略)

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

指数回退逻辑

10 秒本地超时

在这种特殊情况下,我建议像这样使用Policy.WrapAsync( 1 ):

Policy.WrapAsync(OverallTimeoutPolicy(), RetryPolicy(), LocalTimeoutPolicy());
于 2020-08-24T14:39:27.677 回答