我在非常基本的场景中使用Polly在HTTP调用失败时执行指数回退:
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>();
}
我有一个测试应用程序接口,它只在while(true)
中创建HttpListener
和循环。目前,我正在尝试测试当每个呼叫接收500时,客户端是否正确重试。
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秒后发生。
但是,如果我取消对Thread.Sleep
调用的注释,客户端会重试一次,然后就会挂起,直到调用在其他三次重试中超时,这不是正确的行为。
同样的事情也发生在实际的生产API上,这让我相信这不是我的测试API的问题。
发布于 2022-03-03 17:10:08
对于.NET框架和在HttpClient中使用Polly的已知问题,这似乎是一个合适的解决方法。我们必须在重试时处理结果,以便允许多个请求。请参阅关于原始问题here的讨论,以及描述解决方法here的另一讨论。我只是对它进行了简单的测试,以确定它是否有效,但还没有充分研究它可能存在的副作用。
Policy
.Handle<HttpRequestException>()
.OrResult<HttpResponseMessage>(msg => RetryableStatusCodesPredicate(msg.StatusCode))
.RetryAsync(retryCount, onRetry: (x, i) =>
{
x.Result.Dispose(); // workaround for https://github.com/aspnet/Extensions/issues/1700
}));
https://stackoverflow.com/questions/56769241
复制相似问题