[英]Polly won't throw on some exceptions?
I'm using Polly with .net Core.我将 Polly 与 .net 核心一起使用。 My
ConfigureServices
is:我的
ConfigureServices
是:
private static void ConfigureServices()
{
var collection = new ServiceCollection();
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(3);
collection.AddHttpClient<INetworkService, NetworkService>(s=>
{
s.BaseAddress = new Uri("http://google.com:81"); //this is a deliberate timeout url
})
.AddPolicyHandler((a,b)=>GetRetryPolicy(b))
.AddPolicyHandler(timeoutPolicy); ;
...
}
This is the GetRetryPolicy
function:这是
GetRetryPolicy
function:
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(HttpRequestMessage req)
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => httpStatusCodesWorthRetrying.Contains(msg.StatusCode)) // see below
.Or<TimeoutRejectedException>()
.Or<TaskCanceledException>()
.Or<OperationCanceledException>()
.WaitAndRetryAsync(3, retryAttempt =>
{
return TimeSpan.FromSeconds(3);
}, onRetry: (response, delay, retryCount, context) =>
{
Console.WriteLine($"______PollyAttempt_____ retryCount:{retryCount}__FOR_BaseUrl_{req.RequestUri.ToString()}");
});
}
Those are the httpcodes I want to retry:这些是我想重试的httpcode:
static HttpStatusCode[] httpStatusCodesWorthRetrying = {
HttpStatusCode.RequestTimeout, // 408
HttpStatusCode.InternalServerError, // 500
HttpStatusCode.BadGateway, // 502
HttpStatusCode.ServiceUnavailable, // 503
HttpStatusCode.GatewayTimeout // 504
};
Ok.好的。 And this is the actual invocation:
这是实际的调用:
public async Task Work()
{
try
{
HttpResponseMessage response = await _httpClient.GetAsync("");
Console.WriteLine("After work");
}
catch (TimeoutRejectedException ex)
{
Console.WriteLine("inside TimeoutRejectedException");
}
catch (Exception ex)
{
Console.WriteLine("inside catch main http");
}
}
The output is: output 是:
_ PollyAttempt retryCount:1__FOR_BaseUrl_ http://google.com:81/
_ PollyAttempt retryCount:1__FOR_BaseUrl_ http://google.com:81/
_ PollyAttempt retryCount:2__FOR_BaseUrl_ http://google.com:81/_ PollyAttempt retryCount:2__FOR_BaseUrl_ http://google.com:81/
_ PollyAttempt retryCount:3__FOR_BaseUrl_ http://google.com:81/_ PollyAttempt retryCount:3__FOR_BaseUrl_ http://google.com:81/
inside TimeoutRejectedExceptionTimeoutRejectedException 内部
(notice it throws) Which is OK. (注意它抛出)没关系。 Because Polly throws after this invalid URL is timeout.
因为 Polly 在这个无效的 URL 超时后抛出。
But if I change the http://google.com:81/
to an "internal server error" url: (this return 500)但是,如果我将
http://google.com:81/
更改为“内部服务器错误”url:(返回 500)
https://run.mocky.io/v3/9f1b4c18-2cf0-4303-9136-bb67d54d0148https://run.mocky.io/v3/9f1b4c18-2cf0-4303-9136-bb67d54d0148
Then it doesn't throw but continues:然后它不会抛出,而是继续:
_ PollyAttempt retryCount:1__FOR_BaseUrl_ https://run.mocky.io/v3/9f1b4c18-2cf0-4303-9136-bb67d54d0148
_ PollyAttempt retryCount:1__FOR_BaseUrl_ https://run.mocky.io/v3/9f1b4c18-2cf0-4303-9136-bb67d54d0148
_ PollyAttempt retryCount:2__FOR_BaseUrl_ https://run.mocky.io/v3/9f1b4c18-2cf0-4303-9136-bb67d54d0148_ PollyAttempt retryCount:2__FOR_BaseUrl_ https://run.mocky.io/v3/9f1b4c18-2cf0-4303-9136-bb67d54d0148
_ PollyAttempt retryCount:3__FOR_BaseUrl_ https://run.mocky.io/v3/9f1b4c18-2cf0-4303-9136-bb67d54d0148_ PollyAttempt retryCount:3__FOR_BaseUrl_ https://run.mocky.io/v3/9f1b4c18-2cf0-4303-9136-bb67d54d0148
After work下班以后
(notice "after work" at the end) (最后注意“下班后”)
Question:问题:
Why does Polly throw at timeout, But doesn't throw at another condition?为什么 Polly 在超时时抛出,但在其他条件下不抛出? I explictly wrote:
.OrResult(msg => httpStatusCodesWorthRetrying.Contains(msg.StatusCode))
and 500 is one of them.我明确写道:
.OrResult(msg => httpStatusCodesWorthRetrying.Contains(msg.StatusCode))
而 500 就是其中之一。
As @StephenCleary said that's how the Polly works.正如@StephenCleary 所说,Polly 就是这样工作的。
First let me share with you the cleaned up version of your code首先让我与您分享您的代码的清理版本
then I will give you some explanation about the observed behaviours.然后我会给你一些关于观察到的行为的解释。
ConfigureServices
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(3,
onTimeoutAsync: (_, __, ___) => {
Console.WriteLine("Timeout has occured");
return Task.CompletedTask;
});
services.AddHttpClient<INetworkService, NetworkService>(
client => client.BaseAddress = new Uri("https://httpstat.us/500"))
.AddPolicyHandler((_, request) => Policy.WrapAsync(GetRetryPolicy(request), timeoutPolicy));
GetRetryPolicy
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(HttpRequestMessage req)
=> HttpPolicyExtensions
.HandleTransientHttpError()
.Or<TimeoutRejectedException>()
.Or<OperationCanceledException>()
.WaitAndRetryAsync(3,
_ => TimeSpan.FromSeconds(3),
onRetry: (_, __, retryCount, ___) =>
Console.WriteLine($"POLLY retryCount:{retryCount} baseUrl: {req.RequestUri}"));
http://google.com:81
http://google.com:81
TimeoutRejectedException
is thrownTimeoutRejectedException
TimeoutRejectedException
TimeoutRejectedException
https://httpstat.us/500
https://httpstat.us/500
Because there is a lack of EnsureSuccessStatusCode
method call that's why no exception is being thrown.因为缺少
EnsureSuccessStatusCode
方法调用,所以没有抛出异常。
As you can see in the second example the TimeoutPolicy is not triggered at all.正如您在第二个示例中看到的那样,TimeoutPolicy 根本没有被触发。
This is expected behavior.这是预期的行为。 A delegate invocation results in either an exception or a return value.
委托调用会导致异常或返回值。 When the Polly retries are done, then it propagates whatever result was last, whether it is an exception or a return value.
当 Polly 重试完成时,它会传播最后的结果,无论是异常还是返回值。
In this case, the response would have a 500 status code.在这种情况下,响应将具有 500 状态代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.