重试一次后,Polly WaitAndRetryAsync挂起 [英] Polly WaitAndRetryAsync hangs after one retry

查看:473
本文介绍了重试一次后,Polly WaitAndRetryAsync挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在非常基本的情况下使用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 single SendAsync call.
  • Some versions of HttpClient also dispose their content, so it can't be reused in the next SendAsync 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆