使用与重试策略相关联的特定超时时间。

11

我正在以下列方式创建重试策略:

var policy = Policy.Handle<Exception>().WaitAndRetryAsync...

如何为上述重试策略设置超时时间?Policy.TimeoutAsync返回一个TimeoutPolicy,因此我无法像下面这样做:
var policy = Policy.TimeoutAsync(30).Handle<Exception>().WaitAndRetryAsync...

超时时间是否成为所有重试策略的通用设置?
1个回答

36
要合并策略,您需要单独构建每个策略,然后使用 PolicyWrap 进行组合。
要构建一个跨所有重试整体应用的总超时时间(即整个操作跨度):
var overallTimeoutPolicy = Policy.TimeoutAsync(60); 
var waitAndRetryPolicy = Policy
    .Handle<WhateverException>()
    .WaitAndRetryAsync(/* your wait-and-retry specification*/);
var combinedPolicy = overallTimeoutPolicy.WrapAsync(waitAndRetryPolicy);

await combinedPolicy.ExecuteAsync(cancellationToken => ...)

为了对每个特定的尝试设置超时时间,请以另一种顺序包装重试和超时策略:
var timeoutPerTry = Policy.TimeoutAsync(10); 
var waitAndRetryPolicy = Policy
    .Handle<WhateverException>()
    .WaitAndRetryAsync(/* your wait-and-retry specification*/);
var combinedPolicy = waitAndRetryPolicy.WrapAsync(timeoutPerTry);

await combinedPolicy.ExecuteAsync(cancellationToken => ...);

甚至可以同时使用两种超时(每次尝试超时和整个操作超时):

var overallTimeout = Policy.TimeoutAsync(60); 
var timeoutPerTry = Policy.TimeoutAsync(10); 
var waitAndRetryPolicy = Policy
    .Handle<WhateverException>()
    .WaitAndRetryAsync(/* your wait-and-retry specification*/);

var combinedPolicy = Policy
    .WrapAsync(overallTimeout, waitAndRetryPolicy, timeoutPerTry); // demonstrates alternative PolicyWrap syntax

await combinedPolicy.ExecuteAsync(cancellationToken => ...);

PolicyWrap wiki提供完整的语法细节,以及在包装中组合策略时不同顺序的影响建议


回答如下:

超时设置是否适用于我所有的重试策略?

策略适用于您使用它们的任何地方(无论是单独使用还是作为PolicyWrap的一部分)。

您可以线程安全地在多个调用站点使用已配置的任何TimeoutPolicy实例。因此,要将该超时应用为所有重试策略的通用设置,只需在每个调用站点的PolicyWrap中包含相同的TimeoutPolicy实例即可。如果需要,可以安全地将单个TimeoutPolicy实例与不同的重试策略实例组合。

如果您的等待和重试规范以及超时规范对所有调用站点都是通用的,则仅需创建一个涵盖两者的PolicyWrap实例(如上面的代码示例),并在各处重复使用该PolicyWrap实例。同样 - 线程安全。


你好,根据您的评论,这段代码不应该正常工作吗?https://pastebin.com/E6RaTWCn 我设置了1秒超时策略来处理2秒的任务。我期望在日志中看到“fail:timeoutexception”。我还注意到您不建议将ExecuteAndCapture与policywraps一起使用。如果我切换到Execute,最后一次尝试抛出异常会发生什么? - Johan
或者,坚持使用 Thread.Sleep(...),并证明 TimeoutPolicyTimeoutStrategy.Pessimistic 成功超时 - 即使调用者正在等待无法取消的 Thread.Sleep(...),也会让其“放弃”。可取消任务和 TimeoutStrategy.Optimistic 更受欢迎且更节省资源 - 请参见维基百科。 - mountain traveller
示例展示了 TimeoutStrategy.Pessimistic:https://dotnetfiddle.net/xREDBf。(我减少了延迟和尝试次数,以适应 dotnetfiddle 的执行限制) - mountain traveller
示例展示了 TimeoutStrategy.Optimistic:https://dotnetfiddle.net/pnMdSQ。Polly 的超时单元测试中还有更多的示例。 - mountain traveller
1
请检查是否已经设置了超时。如果没有,悲观的超时机制允许调用者在超时时间后退出。但请注意,这正是它所做的。调用者可以退出,但它并不能自动取消已超时的调用。所有细节都在wiki和优秀的Stephen Toub文章中讨论。希望对您有所帮助。 - mountain traveller
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接