Polly Timeout 乐观使用 HttpClientFactory。如何使用取消令牌?

Posted

技术标签:

【中文标题】Polly Timeout 乐观使用 HttpClientFactory。如何使用取消令牌?【英文标题】:Polly Timeout optimistic using HttpClientFactory. How can I use cancellation token? 【发布时间】:2022-01-20 04:55:35 【问题描述】:

我想了解如何使用 HttpClientFactory 使用 Polly 实施乐观超时策略。

在网上的例子中,调用异步方法时使用超时策略能够传递取消令牌。但是如果我从配置服务中设置超时策略,如the guide 所示),我该如何管理取消令牌?

在示例代码中,来自链接的指南,我看到了:

var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(10); // Timeout for an individual try

serviceCollection.AddHttpClient("GitHub", client =>

    client.BaseAddress = new Uri("https://api.github.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
    client.Timeout = TimeSpan.FromSeconds(60); // Overall timeout across all tries
)
.AddPolicyHandler(retryPolicy)
.AddPolicyHandler(timeoutPolicy);

【问题讨论】:

我的帖子回答你的问题了吗? 【参考方案1】:

您应该将chain 重试和超时策略合并为一个组合策略。

你有两个选择:

Wrap方法

.AddPolicyHandler(retryPolicy.Wrap(timeoutPolicy))
timeoutPolicy 是内部策略,因此它分别适用于每次尝试 retryPolicy 是外部策略,因此它是超时策略的首要任务 注意订购事项(我会在后面详细介绍)

PolicyWrap

.AddPolicyHandler(Policy.Wrap(retryPolicy,timeoutPolicy))
第一个参数是最外层的策略 最后一个参数是最内部的策略

顺序很重要

您应该知道,以下两种组合策略非常不同:

Policy.Wrap(retryPolicy,timeoutPolicy)
Policy.Wrap(timeoutPolicy, retryPolicy)
在第一种情况下,您有一个本地超时,它适用于每次重试尝试 在第二种情况下,您有一个 全局 超时,该超时应用于整个重试活动

推进这个想法,您可以通过定义全局超时来避免设置 HttpClient 的 Timeout 属性:

var localTimeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(10);
var globalTimeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(60);
var resilientStrategy = Policy.Wrap(globalTimeoutPolicy, retryPolicy, localTimeoutPolicy);

serviceCollection.AddHttpClient("GitHub", client =>

    client.BaseAddress = new Uri("https://api.github.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
)
.AddPolicyHandler(resilientStrategy);

更新 #1 乐观超时

Polly 的超时确实支持 optimistic 和 pessimistic 超时。换句话说,Polly 可以尝试取消那些确实预期 CancellationToken(乐观)的待包装方法以及那些不预期(悲观)的方法。默认是前者。

在乐观的情况下,您有两种选择:

让政策执行取消
await policy.ExecuteAsync(
   async ct => await httpClient.SendAsync(..., ct),
   CancellationToken.None);
或将其与您的自定义 CTS 组合/链接
await policy.ExecuteAsync(
   async ct => await httpClient.SendAsync(..., ct),
   cancellationSource.Token);

如果您在启动期间注册您的命名/键入客户端,那么您只能使用第一个选项。因为policy.ExecuteAsync 将代表您(隐式)被调用。

如果您注册了一个类型化的客户端并在该客户端中定义了策略,那么您就是在显式调用ExecuteAsync,您可以在其中决定使用哪个版本。

【讨论】:

以上是关于Polly Timeout 乐观使用 HttpClientFactory。如何使用取消令牌?的主要内容,如果未能解决你的问题,请参考以下文章

Polly

Polly

如何为每个 url 使用 Polly 和 IHttpClientFactory

使用最小起订量测试 Polly 重试策略

使用 polly 并行化任务

使用 Polly 实现复杂策略(超时重试)