2

我目前正在同时使用 Polly 和 Flurl,但我有一个共同的重试策略,我必须将其添加到每个请求中。我注意到 Polly 允许您使用 AddPolicyHandler(...) 设置默认值,但这需要一个 IHttpClientBuilder 并且我看不出有任何方法可以从 Flurl 中获取它。

我认为重载 DefaultHttpClientFactory 可能是要走的路,但这只能让我访问 HttpClient,而不是 IHttpClientBuilder。

我知道我可以制作自己的 HttpClients 并将它们传递给 Flurl,但如果可以的话,我宁愿避免这种情况,因为我希望 Flurl 管理它们的生命周期。

目前有没有办法做我想做的事?

4

1 回答 1

9

好问题。Flurl 为您提供了所有必要的钩子来执行此操作。首先定义一个DelegatingHandler采用 Polly 策略的:

public class PollyHandler : DelegatingHandler
{
    private readonly IAsyncPolicy<HttpResponseMessage> _policy;

    public PollyHandler(IAsyncPolicy<HttpResponseMessage> policy) {
        _policy = policy;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
        return _policy.ExecuteAsync(ct => base.SendAsync(request, ct), cancellationToken);
    }
}

然后创建一个自定义IHttpClientFactory,返回您的自定义处理程序,并将默认处理程序作为其InnerHandler

public class PollyFactory : DefaultHttpClientFactory
{
    private readonly IAsyncPolicy<HttpResponseMessage> _policy;

    public PollyFactory(IAsyncPolicy<HttpResponseMessage> policy) {
        _policy = policy;
    }

    public override HttpMessageHandler CreateMessageHandler() {
        return new PollyHandler(_policy) {
            InnerHandler = base.CreateMessageHandler()
        };
    }
}

最后,在应用启动时,定义您的策略并将其注册到 Flurl:

var policy = Policy
    .Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    .RetryAsync(5);

FlurlHttp.Configure(settings => settings.HttpClientFactory = new PollyFactory(policy));

一个重要的注意事项是,这种方法不适用于处理 FlurlHttpException 的策略。那是因为您在HttpMessageHandler此处拦截呼叫。Flurl 将响应和错误转换为FlurlHttpException更高的堆栈,因此这些不会被这种方法捕获/重试。上面示例中的策略会捕获HttpRequestExceptionHttpResponseMessage(使用非 2XX 状态代码),这将起作用。

于 2018-09-11T20:48:14.377 回答