gpt4 book ai didi

c# - HttpClient Polly WaitAndRetry 策略

转载 作者:行者123 更新时间:2023-12-03 23:05:51 29 4
gpt4 key购买 nike

任何人都知道为什么下面的政策在 3 次而不是 10 次后停止重试?

IAsyncPolicy<HttpResponseMessage> httpWaitAndRetryPolicy =
Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
.OrHandle<Exception>(r => true)
.WaitAndRetryAsync(10, retryAttempt => TimeSpan.FromSeconds(2));
我将重试尝试设置为 10 并测试带有 BadRequest 失败的 http post 调用。
但它只重试 3 次然后停止直到超时并抛出异常
  ----> System.Threading.Tasks.TaskCanceledException : A task was canceled.
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at HttpRetry.Lab.Tests.ServiceTest.WhenPostWrongAlert_ThenRecoversProperly() in C:\ServiceTest.cs:line 56
--TaskCanceledException


15:57:03.6367 INFO HttpClientProvider - Configuring client xxxxxxxx:1234/api/" timeout=00:02:00
15:57:03.6636 INFO Service - POST xxxx/xxxxxxx
15:57:04.2051 INFO HttpClientProvider - Retrying retryCount=1 sleepDuration=00:00:02 result=Polly.DelegateResult`1[System.Net.Http.HttpResponseMessage]
15:57:06.6880 INFO HttpClientProvider - Retrying retryCount=2 sleepDuration=00:00:02 result=Polly.DelegateResult`1[System.Net.Http.HttpResponseMessage]
15:59:03.6811 INFO HttpClientProvider - Retrying retryCount=3 sleepDuration=00:00:02 result=Polly.DelegateResult`1[System.Net.Http.HttpResponseMessage]
15:59:03.6811 ERROR ServiceTest - System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at HttpRetry.Lab.Service.<PostAsync>d__4.MoveNext() in C:\Service.cs:line 38
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at HttpRetry.Lab.Tests.ServiceTest.<PostAsync>d__4.MoveNext() in C:\ServiceTest.cs:line 27

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>());
确认问题的根本原因:
我不知道是什么导致了这种症状,但看起来请求连接不会被释放,除非显式调用 Dispose HttpResponseMessage OnRetry。
当前的解决方案是在 WaitAndRetryAsync 中设置 OnRetry 并处理响应。一切正常,无需更改 ServicePointManager.DefaultConnectionLimit

最佳答案

你的超时
正如我所看到的,您在 HttpClient 级别上有 1 分钟的全局超时。这将抛出 TaskCanceledException即使您可能期望 TimeoutException .
如果您希望收到 TimeoutException那么你必须通过 RequestTimeout 指定一个基于请求的超时。 HttpRequestMessage 的属性(property).更多详情请查看the following link .
您的重试
您的重试逻辑定义了 3 次(或 10 次)重试,惩罚为 5 秒。 3 次重试意味着 4 次尝试,因为有一个初始(第 0 个)请求,它超出了重试范围。如果失败,那么第一次重试将成为第二次尝试。
所以流程将如下所示:

  • 发出初始请求 << 第一次尝试
  • 初始请求失败
  • 触发重试逻辑
  • 5秒处罚曝光
  • 第一次重试逻辑触发 << 第二次尝试
  • 第二次尝试失败
  • 触发重试逻辑
  • 5秒处罚曝光
  • 第二次重试逻辑触发 << 第三次尝试
  • ...

  • 如果所有这些都可以在一秒钟内完成,那么 HttpClient 将抛出 TaskCanceledExpcetion由于全局超时。
    Polly 的超时策略
    Polly 也支持本地和全局超时策略。有一个 Timeout policy , 这两种方式都可以使用。
    如果您的超时策略包含在重试中,它可以充当本地超时: retryPolicy.WrapAsync(timeoutPolicy);如果您的重试策略包含在超时内,它可以充当全局超时: timeoutPolicy.WrapAsync(retryPolicy);当然,您也可以同时拥有全局和本地超时: Policy.WrapAsync(globalTimeoutPolicy, retryPolicy, localTimeoutPolicy);我强烈建议您考虑使用 Polly 的 Timeout 而不是 HttpClient 的 Timeout,以便在一个地方定义您的弹性策略。
    请记住,超时策略将抛出 TimeoutRejectedException如果超时没有响应。因为您的重试处理各种异常 ( .OrHandle<Exception>()),所以您不需要修改重试策略。
    Polly 的瞬时故障的错误处理
    有一个名为 的 nuget 包Microsoft.Extensions.Http.Polly ( 1 ),它定义了几个有用的实用程序。其中之一是 HttpPolicyExtensions.HandleTransientHttpError()它捕获 HttpRequestException并检查响应的状态码是否为 5xx 408 (请求超时)。
    也可能值得考虑使用它。
    调试策略
    每个不同的策略都定义了回调,以提供了解它们如何工作的能力。在重试的情况下,它被称为 onRetryonRetryAsync分别用于同步或异步重试。您通过在您的 WaitAndRetryAsync 中提供以下委托(delegate)您可以获得非常有用的信息:
    onRetryAsync: (exception, delay, times, context) => {
    //TODO: logging
    }

    关于c# - HttpClient Polly WaitAndRetry 策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62806212/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com