csc*_*h99 5 c# rest dotnet-httpclient polly retry-logic
有人知道为什么下面的策略在 3 次而不是 10 次后停止重试吗?
IAsyncPolicy<HttpResponseMessage> httpWaitAndRetryPolicy =
Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
.OrHandle<Exception>(r => true)
.WaitAndRetryAsync(10, retryAttempt => TimeSpan.FromSeconds(2));
Run Code Online (Sandbox Code Playgroud)
我将重试尝试设置为 10 并测试 http post 调用,但 BadRequest 失败。但只重试了3次就停止了,直到超时并抛出异常
IAsyncPolicy<HttpResponseMessage> httpWaitAndRetryPolicy =
Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
.OrHandle<Exception>(r => true)
.WaitAndRetryAsync(10, retryAttempt => TimeSpan.FromSeconds(2));
Run Code Online (Sandbox Code Playgroud)
var serviceProvider = serviceConnection.AddHttpClient(connection.Name, c =>
{
c.BaseAddress = new Uri(connection.BaseUrl);
c.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{connection.UserName}:{connection.Password}")));
c.Timeout = connection.Timeout; // Timeout is TimeSpan.FromSeconds(120)
})
.AddPolicyHandler(httpWaitAndRetryPolicy)
.Services.BuildServiceProvider();
HttpClientFactories.Add(connection.Name, serviceProvider.GetService<IHttpClientFactory>());
Run Code Online (Sandbox Code Playgroud)
确认了问题的根本原因:我不知道是什么原因导致了该症状,但看起来请求连接不会被释放,除非显式调用Dispose HttpResponseMessage OnRetry. 当前的解决方案是设置OnRetry并WaitAndRetryAsync配置响应。一切正常,无需更改ServicePointManager.DefaultConnectionLimit
正如我所看到的,您在 HttpClient 级别上有一个全局 1 分钟超时。TaskCanceledException即使您可能期望,这也会引发TimeoutException。
如果您希望接收TimeoutException,则必须通过RequestTimeout的属性指定基于请求的超时HttpRequestMessage。欲了解更多详情,请查看以下链接。
您的重试逻辑定义了 3 次(或 10 次)重试,并有 5 秒的惩罚。3 次重试意味着 4 次尝试,因为有一个初始(第 0 个)请求,该请求超出了重试范围。如果失败,则第一次重试将成为第二次尝试。
所以流程将如下所示:
如果所有这些都不能在一分钟内完成,那么 HttpClient 将TaskCanceledExpcetion因全局超时而抛出异常。
Polly 还支持本地和全局超时策略。有一个超时策略,可以以两种方式使用。
如果您的超时策略包含在重试中,它可以充当本地超时:
retryPolicy.WrapAsync(timeoutPolicy);
如果您的重试策略包含在超时内,它可以充当全局超时:
timeoutPolicy.WrapAsync(retryPolicy);
当然,您也可以同时设置全局和本地超时:
Policy.WrapAsync(globalTimeoutPolicy, retryPolicy, localTimeoutPolicy);
我强烈鼓励您考虑使用 Polly 的 Timeout 而不是 HttpClient 的 Timeout,以便有一个地方可以定义弹性策略。
请记住,TimeoutRejectedException如果超时后没有响应,超时策略将抛出异常。因为您的重试会处理所有类型的异常 ( .OrHandle<Exception>()),所以您不需要修改重试策略。
有一个名为Microsoft.Extensions.Http.Polly ( 1 ) 的 nuget 包,它定义了几个有用的实用程序。其中之一是HttpPolicyExtensions.HandleTransientHttpError()
它捕获HttpRequestException并检查响应的状态代码是否为5xx或408 (RequestTimeout)。
也可能值得考虑使用它。
每个不同的策略都定义了回调,以提供了解它们如何工作的能力。如果重试,则分别调用onRetryoronRetryAsync进行同步或异步重试。通过在您的内部提供以下委托,WaitAndRetryAsync您可以获得真正有用的信息:
onRetryAsync: (exception, delay, times, context) => {
//TODO: logging
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9057 次 |
| 最近记录: |