重试一次后,Polly WaitAndRetryAsync挂起 [英] Polly WaitAndRetryAsync hangs after one retry
问题描述
我在非常基本的情况下使用Polly在HTTP调用失败的情况下进行指数补偿:
I'm using Polly in very basic scenario to do exponential backoff if an HTTP call fails:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return await HandleTransientHttpError()
.Or<TimeoutException>()
.WaitAndRetryAsync(4, retryAttempt => TimeSpan.FromSeconds(Math.Pow(3, retryAttempt)))
.ExecuteAsync(async () => await base.SendAsync(request, cancellationToken).ConfigureAwait(false));
}
private static PolicyBuilder<HttpResponseMessage> HandleTransientHttpError()
{
return Policy
.HandleResult<HttpResponseMessage>(response => (int)response.StatusCode >= 500 || response.StatusCode == System.Net.HttpStatusCode.RequestTimeout)
.Or<HttpRequestException>();
}
我有一个仅创建HttpListener
并在while(true)
中循环的测试API.目前,我正在尝试测试客户端在每次收到500个电话时是否正确重试.
I have a test API that just creates an HttpListener
and loops in a while(true)
. Currently, I'm trying to test if the client retries correctly when receiving 500 for every single call.
while (true)
{
listener.Start();
Console.WriteLine("Listening...");
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
response.StatusCode = (int)HttpStatusCode.InternalServerError;
//Thread.Sleep(1000 * 1);
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
listener.Stop();
}
使用上述代码,所有方法都可以正常工作,并且分别在等待3、9、27和81秒后重试.
With the above code all works well and the retries happen after 3, 9, 27 and 81 seconds of waiting, respectively.
但是,如果我取消对Thread.Sleep
调用的注释,客户端将重试一次,然后挂起,直到该调用对其他3次重试超时为止.
However, if I uncomment the Thread.Sleep
call, the client retries once and then just hangs until the call times out for the other 3 retries, which is not the correct behavior.
实际的生产API也会发生同样的事情,这使我相信测试API并不是问题.
The same thing also happens with the actual production API, which leads me to believe it's not a problem with my test API.
推荐答案
在内部使用Polly HttpClient
效果不是很好.单个SendAsync
旨在成为单个调用.即:
Using Polly within HttpClient
doesn't work very well. A single SendAsync
is intended to be a single call. I.e.:
- 任何
HttpClient
超时都将应用于单个SendAsync
呼叫. -
HttpClient
的某些版本也处理其内容,因此不能 在下一个SendAsync
调用中可以重复使用. - 如评论中所述, 这种挂起是已知的 问题,并且不能 由Polly修复.
- Any
HttpClient
timeouts will apply to the singleSendAsync
call. - Some versions of
HttpClient
also dispose their content, so it can't be reused in the nextSendAsync
call. - As noted in the comments, this kind of hang is a known issue and cannot be fixed by Polly.
底线:覆盖SendAsync
对于添加请求前和请求后逻辑非常有用.这不是重试的正确位置.
Bottom line: overriding SendAsync
is great for adding pre-request and post-request logic. It's not the right place to retry.
相反,请使用常规的HttpClient
并让您的Polly逻辑在GetStringAsync
(或任何其他)调用的外部中重试.
Instead, use a regular HttpClient
and have your Polly logic retry outside the GetStringAsync
(or whatever) call.
这篇关于重试一次后,Polly WaitAndRetryAsync挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!