如何让Polly断路器仅统计重试最后一次失败的异常?
我在HttpClient中使用Polly的三个策略:Retry(重试)、CircuitBreaker(断路器)、Timeout(超时)。希望断路器仅在重试的最后一次失败时才统计异常,而非每次重试失败都算入断路器计数。比如重试次数设为3时,期望行为是:
重试1 -> HttpRequestException
重试2 -> HttpRequestException
重试3 -> HttpRequestException
断路器异常计数 1
重试1 -> HttpRequestException
重试2 -> HttpRequestException
重试3 -> HttpRequestException
断路器异常计数 2
...
但当前策略组合后,重试三次失败就触发了断路器,不符合预期。
问题根源
你当前的策略组合顺序是Retry -> CircuitBreaker -> Timeout,Polly的WrapAsync是从右到左执行的,这意味着每次重试失败都会经过断路器,导致每一次重试失败都被断路器统计。三次重试失败后,断路器的异常计数直接达到阈值,触发了断路逻辑。
解决方案:调整策略组合顺序
要实现「一轮重试全部失败后才让断路器统计异常」的效果,必须让断路器包裹重试策略。正确的组合顺序应该是:
Policy.WrapAsync(policyConsentsService.HttpConsentCircuitBreakerPolicy, policyService.HttpRetryPolicy, policyService.HttpTimeoutPolicy);
这个组合的实际执行流程是:
- 最右侧的
HttpTimeoutPolicy先执行,控制单次请求的超时 - 然后执行
HttpRetryPolicy,完成所有重试尝试 - 只有当整个重试流程(3次)全部失败时,才会触发最左侧的
HttpConsentCircuitBreakerPolicy,让其异常计数+1
这样就能严格符合你的预期:每一轮重试全部失败后,断路器才统计一次异常,累计到设定阈值(比如3次)才会打开断路器。
额外验证点
确保重试策略和断路器的异常处理范围一致。比如你的重试策略用HandleTransientHttpError()处理临时HTTP错误,断路器也同样包含该规则并加上TimeoutRejectedException,避免出现重试未处理的异常提前触发断路器的情况。
内容的提问来源于stack exchange,提问作者pampua84

