c# - Polly 如何能够重新发送相同的 HTTP 请求?

标签 c# asp.net-core dotnet-httpclient polly retry-logic

HttpRequestMessage 只能发送一次。尝试重新发送它会导致 InvalidOperationException

那么 Polly 如何能够规避这种行为,换句话说,当将 AddPolicyHandler 与重试策略一起使用时,幕后发生了什么?我知道它使用 DelegatingHandler 但它如何能够多次处理同一消息?

最佳答案

TL;DR:这与 Polly 无关。


让我们从一个示例开始,该示例在第二次尝试时失败并出现 InvalidOperationException

var request = new HttpRequestMessage(HttpMethod.Get, "https://httpstat.us/500");

var httpClient = new HttpClient(new HttpClientHandler());
for(int i = 0; i < 3; i++)
{
    var result = await httpClient.SendAsync(request);
    result.StatusCode.Dump();
}

如果我们将请求对象的创建移到 for 循环内,那么一切都会好起来的。但让我们将其保留在 for 之外。

让我们创建一个简单的委托(delegate)处理程序

public class RetryHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpResponseMessage result = null;
        for(int i = 0; i < 3; i++)
        {
            result = await base.SendAsync(request, cancellationToken);
            "Retried".Dump();
        }
        return result;
    }
}

让我们使用它

var handler = new RetryHandler();
handler.InnerHandler = new HttpClientHandler();

var httpClient = new HttpClient(handler);
var request = new HttpRequestMessage(HttpMethod.Get, "https://httpstat.us/500");

var result = await httpClient.SendAsync(request);
result.StatusCode.Dump();

此版本不会抛出任何 InvalidOperationException


那么,为什么后者有效而前者无效?

CheckRequestMessage 抛出 InvalidOperationException HttpClient

的方法
private static void CheckRequestMessage(HttpRequestMessage request)
{
    if (!request.MarkAsSent())
    {
        throw new InvalidOperationException(SR.net_http_client_request_already_sent);
    }
}

此方法正在由 CheckRequestBeforeSend 调用。这是 SendAsync 的第一个命令。此公共(public) SendAsync 调用其 base's SendAsync 。这里的base是一个HttpMessageInvoker,其中deals with the HttpMessageHandler .

长话短说:

  • 如果您想在 HttpClient 之外重用 HttpRequestMessage,那么由于 CheckRequestMessage 调用,第二次尝试将会失败
  • >
  • 如果您想在 DelegatingHandler (HttpMessageHandler) 中重用 HttpRequestMessage,那么它不会失败,因为 HttpMessageInvoker does not care关于重用

关于c# - Polly 如何能够重新发送相同的 HTTP 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76058694/

相关文章:

c# - 如何在执行 Web 请求时指定仅连接超时?

f# - 如何从 F# 使用 HttpClient?

c# - 从 html 中查找与正则表达式模式匹配的文本

c# - 具有可选参数/默认参数值的 ASP.NET5 MVC 6 路由

c# - .NET Core 应用程序中添加服务引用的简单性是否已被删除?

c# - eBay FileTransferService - 请指定具有有效格式的文件

c# - List<T>.Last() 是否枚举集合?

c# - 我可以从一个线程使用 System.Threading.Timer 启动多少个线程(计时器)?

c# - 使用 Task.Factory.StartNew 时更新 UI 标签

asp.net-core - Asp.net 5 DNX 和 DNU 无法在 Windows Server 2008 R2 中工作