gpt4 book ai didi

dotnet-httpclient - 使用 "AddPolicyHandler"时 Polly 策略不起作用

转载 作者:行者123 更新时间:2023-12-04 12:37:06 25 4
gpt4 key购买 nike

我有一个应用程序请求经过身份验证的服务,需要通过 access_token .
我的想法是使用 Polly 重试 access_token已过期。
我在 .NET Core 3.1 应用程序中使用 Refit (v5.1.67) 和 Polly (v7.2.1)。
服务注册如下:

services.AddTransient<ExampleDelegatingHandler>();

IAsyncPolicy<HttpResponseMessage> retryPolicy = Policy<HttpResponseMessage>
.Handle<ApiException>()
.RetryAsync(1, (response, retryCount) =>
{
System.Diagnostics.Debug.WriteLine($"Polly Retry => Count: {retryCount}");
});

services.AddRefitClient<TwitterApi>()
.ConfigureHttpClient(c =>
{
c.BaseAddress = new Uri("https://api.twitter.com/");
})
.AddHttpMessageHandler<ExampleDelegatingHandler>()
.AddPolicyHandler((sp, req) =>
{
//this policy does not works, because the exception is not catched on
//"Microsoft.Extensions.Http.PolicyHttpMessageHandler" (DelegatingHandler)
return retryPolicy;
});
public interface TwitterApi
{
[Get("/2/users")]
Task<string> GetUsers();
}
public class ExampleDelegatingHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
return await base.SendAsync(request, cancellationToken);
}
catch (Exception)
{
//Why do not catch the exception?
throw;
}
}
}
重试策略不起作用!
分析这个问题,我意识到异常没有被 HttpClient 的 DelegatingHandler 捕获。 .自 AddPolicyHandler语句正在生成 DelegatingHandler ( PolicyHttpMessageHandler ) 来执行策略并且在那里没有捕获异常,策略永远不会执行。我意识到问题只发生在异步场景中,可以发送请求。在同步场景中它有效(例如:超时)。
为什么内部没有捕获异常DelegatingHandler ??
我附上了一个模拟 Twitter 调用的示例项目。
https://www.dropbox.com/s/q1797rq1pbjvcls/ConsoleApp2.zip?dl=0
外部引用:
https://github.com/reactiveui/refit#using-httpclientfactory
https://www.hanselman.com/blog/UsingASPNETCore21sHttpClientFactoryWithRefitsRESTLibrary.aspx
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1

最佳答案

TL;DR:AddPolicyHandler 的顺序和 AddHttpMessageHandler确实很重要。

我用 HttpClient 重现了这个问题(所以没有 retrofit )。
用于测试的类型化 HttpClient

public interface ITestClient
{
Task<string> Get();
}

public class TestClient: ITestClient
{
private readonly HttpClient client;
public TestClient(HttpClient client)
{
this.client = client;
}
public async Task<string> Get()
{
var resp = await client.GetAsync("http://not-existing.site");
return "Finished";
}
}
测试用 Controller
[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
private readonly ITestClient client;

public TestController(ITestClient client)
{
this.client = client;
}

[HttpGet]
public async Task<string> Get()
{
return await client.Get();
}
}
用于测试的 DelegateHandler
public class TestHandler: DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
return await base.SendAsync(request, cancellationToken);
}
catch (System.Exception ex)
{
_ = ex;
throw;
}
}
}

订购 #1 - 处理程序、政策
启动
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<TestHandler>();
services.AddHttpClient<ITestClient, TestClient>()
.AddHttpMessageHandler<TestHandler>() //Handler first
.AddPolicyHandler(RetryPolicy()); //Policy second
}

private IAsyncPolicy<HttpResponseMessage> RetryPolicy()
=> Policy<HttpResponseMessage>
.Handle<HttpRequestException>()
.RetryAsync(1, (resp, count) =>
{
Console.WriteLine(resp.Exception);
});
执行顺序
  • TestControllerGet
  • TestClientGet
  • TestHandlerSendAsynctry
  • RetryPolicyonRetry
  • TestHandlerSendAsynccatch
  • TestControllerGet失败 HttpRequestException (内部:SocketException)

  • 因此,这里不会触发重试策略。
    订购 #2 - 政策、处理程序
    启动
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddControllers();
    services.AddTransient<TestHandler>();
    services.AddHttpClient<ITestClient, TestClient>()
    .AddPolicyHandler(RetryPolicy()) //Policy first
    .AddHttpMessageHandler<TestHandler>(); //Handler second
    }

    private IAsyncPolicy<HttpResponseMessage> RetryPolicy()
    => Policy<HttpResponseMessage>
    .Handle<HttpRequestException>()
    .RetryAsync(1, (resp, count) =>
    {
    Console.WriteLine(resp.Exception);
    });
    执行顺序
  • TestControllerGet
  • TestClientGet
  • TestHandlerSendAsynctry
  • TestHandlerSendAsynccatch
  • RetryPolicyonRetry
  • TestHandlerSendAsynctry
  • TestHandlerSendAsynccatch
  • TestControllerGet失败 HttpRequestException (内部:SocketException)

  • 因此,这里重试策略已被触发。

    关于dotnet-httpclient - 使用 "AddPolicyHandler"时 Polly 策略不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63460681/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com