Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用polly c在http请求超时时重试多次#_C#_Asp.net Mvc_Connection Timeout_Polly - Fatal编程技术网

C# 使用polly c在http请求超时时重试多次#

C# 使用polly c在http请求超时时重试多次#,c#,asp.net-mvc,connection-timeout,polly,C#,Asp.net Mvc,Connection Timeout,Polly,我最初的意图是在请求本身超时时重试多次,例如,当尝试与另一个微服务通信时,该微服务中断了几秒钟,希望这是暂时的失败。如果有一个更简单的解决方案,那就足够了。 我决定使用包装策略手动设置每次重试的超时时间,希望获得相同的结果 我在这里看到了一个类似的解决方案,没有使用httpclientfactory,但它不适合我 我的代码如下所示: services.AddHttpClient("retryclient", client => { client.Timeout = TimeSpan

我最初的意图是在请求本身超时时重试多次,例如,当尝试与另一个微服务通信时,该微服务中断了几秒钟,希望这是暂时的失败。如果有一个更简单的解决方案,那就足够了。 我决定使用包装策略手动设置每次重试的超时时间,希望获得相同的结果

我在这里看到了一个类似的解决方案,没有使用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)));
services.AddHttpClient(“retryclient”,客户端=>
{
client.Timeout=TimeSpan.FromSeconds(100);
}).AddPolicyHandler((服务,请求)=>
Policy.HandleResult(r=>
{
返回r.StatusCode==HttpStatusCode.NotFound;//(1)
}).
.ORTRANSIESSNTTTPEROR()。
WaitAndRetryAsync(5,RetryAttract=>TimeSpan.FromSeconds(RetryAttract),
onRetry:(异常、timespan、RetryAttention、上下文)=>
{///使用服务记录//});
}).WrapAsync(Policy.TimeoutAsync(1));
我已经检查了重试策略在我尝试访问“未找到”地址而不包装超时策略时是否有效,并且它工作正常。我还尝试将第(1)行与状态代码HttpStatusCode.RequestTimeout一起使用,而不是在我的案例中找不到,但它不起作用

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

编辑:进一步阅读后,我的问题似乎是在策略处理中,我没有访问HttpClient的取消令牌。我假设我可以通过重写sendAsync方法来修复它,如link中所示。在创建工厂时,有没有一种优雅的方法可以做到这一点?

在一个标有以下标签的部分中介绍了这一点:

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

因此:

services.AddHttpClient(“retryclient”,客户端=>
{
client.Timeout=TimeSpan.FromSeconds(100);
}).AddPolicyHandler((服务,请求)=>
Policy.HandleResult(r=>
{
返回r.StatusCode==HttpStatusCode.NotFound;//(1)
}).
.OrTransientHttpError()
.或()**
.WaitAndRetryAsync(5,RetryAttenting=>TimeSpan.FromSeconds(RetryAttenting),
onRetry:(异常、timespan、RetryAttention、上下文)=>
{///使用服务记录//});
})
.WrapAsync(Policy.TimeoutAsync(1));

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

请注意,如果客户端的超时时间太接近策略超时时间,它可能仍然会失败,并且不会再次重试。我不知道为什么会发生这种情况,但我可以将客户端的超时设置为足够大的数字,这对我来说是有效的。同意:这在文档中有说明:“
HttpClient.timeout
将作为整体超时应用于通过
HttpClient
进行的每个调用,包括重试之间的所有尝试和等待。”
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)));