【问题标题】:Retry multiple times when http request times out using polly c#当http请求超时时重试多次使用polly c#
【发布时间】:2020-08-09 23:16:37
【问题描述】:

我的初衷是在请求本身超时时重试多次,例如尝试与另一个微服务通信时,该微服务已关闭几秒钟,希望这是暂时的失败。如果有一个更简单的解决方案来做到这一点就足够了。 我决定使用包装策略手动设置每次重试超时,希望达到相同的结果。

我在Use a specific timeout connected to a retrypolicy 看到了一个类似的解决方案,不使用 httpclientfactory,但它对我不起作用。

我的代码如下所示:

services.AddHttpClient("retryclient", client =>
{
    client.Timeout = TimeSpan.FromSeconds(100);
}).AddPolicyHandler((servs, request) =>
    Policy.HandleResult<HttpResponseMessage>(r =>
        {
            return r.StatusCode == HttpStatusCode.NotFound; //(1)
        }).
.OrTransiesntHttpError().
WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
    onRetry: (exception, timespan, retryAttempt, context) =>
        { // using servs to log // });
}).WrapAsync(Policy.TimeoutAsync(1)));

当我尝试访问“未找到”地址而不包装超时策略时,我已检查重试策略是否有效,并且它工作正常。我还尝试将第 (1) 行与状态代码 HttpStatusCode.RequestTimeout 一起使用,而不是在我的情况下找不到,但它不起作用。

当我使用包装并尝试访问已关闭的服务时,它会在第一次尝试时抛出Polly.Timeout.TimeoutRejectedException,正如我所预料的那样,但不会再次重试。我想不出一种方法来重试多次,或者为每次重试设置超时,或者只是在请求本身超时而不使用超时策略时。

编辑:在进一步阅读https://cm.engineering/transient-timeouts-and-the-retry-rabbit-hole-net-4-5-f406cebbf194 之后,我的问题似乎出在策略处理内部,我无权访问 HttpClient 的取消令牌。我假设我可以通过覆盖链接中所示的 sendAsync 方法来修复它。在创建工厂时是否有一种优雅的方式来做同样的事情?

【问题讨论】:

    标签: c# asp.net-mvc connection-timeout polly


    【解决方案1】:

    Polly documentation on HttpClientFactory 在标记为 applying timeouts 的部分中对此进行了介绍:

    如果任何个人尝试超时,您可能希望重试策略重试。为此,请让重试策略处理 Polly 的超时策略引发的 TimeoutRejectedException

    所以:

    services.AddHttpClient("retryclient", client =>
    {
        client.Timeout = TimeSpan.FromSeconds(100);
    }).AddPolicyHandler((servs, request) =>
        Policy.HandleResult<HttpResponseMessage>(r =>
            {
                return r.StatusCode == HttpStatusCode.NotFound; //(1)
            }).
    .OrTransientHttpError()
    .Or<TimeoutRejectedException>() // ** ADDED **
    .WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
        onRetry: (exception, timespan, retryAttempt, context) =>
            { // using servs to log // });
    })
    .WrapAsync(Policy.TimeoutAsync(1)));
    

    Polly 将CancellationToken 正确传递给内部.SendAsync() 调用;不需要对此进行任何更改。

    【讨论】:

    • 请注意,如果客户端的超时时间太接近策略超时时间,它可能仍然会失败并且不会重试。我不确定为什么会发生这种情况,但我可以将客户端的超时设置为足够大的数字,它对我有用。
    • 同意:文档对此进行了介绍,其中说:“HttpClient.Timeout 将作为通过HttpClient 的每个完整调用的总体超时,包括所有尝试和重试之间的等待。”
    猜你喜欢
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 2022-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多