用 Policy.WrapAsync(或 Wrap)将多个策略按执行顺序嵌套包装,外层控整体(如超时),内层处理细节(如重试、熔断);顺序决定生效优先级,类型须一致,异常为最内层原始异常。
多个Polly策略怎么串起来用
直接说结论:用 Policy.WrapAsync(或 Policy.Wrap)把多个策略按执行顺序“包”成一个,不是简单叠加,而是形成嵌套调用链。外层策略控制整体行为(比如超时),内层策略处理具体异常(比如重试、熔断)。
常见错误是把 RetryPolicy 和 CircuitBreakerPolicy 分开 await,结果重试逻辑完全绕过熔断器;或者误用 .Or() 想合并策略——那只是扩展异常类型匹配,不是组合策略行为。
-
Wrap的顺序很重要:最外层策略最先生效,最内层策略最接近实际委托。例如TimeoutPolicy.WrapAsync(RetryPolicy.WrapAsync(CircuitBreakerPolicy))表示:先走熔断判断 → 再决定是否重试 → 最后被超时兜底中断 - 所有被包装的策略必须类型一致:要么全是
AsyncPolicy,要么全是AsyncPolicy(无返回值)。混用会导致编译失败 - 如果策略里用了
Context(比如传"operation-id"),外层策略的Context会透传给内层,但各策略的onRetry/onBreak回调中拿到的Context是同一份引用,注意别意外覆盖
带返回值的异步策略怎么包装
处理 HTTP 调用这类有返回值的场景,必须用泛型版本的 WrapAsync,否则编译不通过。策略声明和包装都得对齐类型。
例如封装一个带熔断 + 重试 + 超时的 HttpClient.GetAsync 调用:
var circuitBreaker = Policy
.Handle()
.CircuitBreakerAsync(5, TimeSpan.FromMinutes(1));var retry = Policy
.Handle()
.OrResult(r => !r.IsSuccessStatusCode)
.WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2) });var timeout = Policy.TimeoutAsync(5);
var wrapped = Policy.WrapAsync(circuitBreaker, retry, timeout); // 注意顺序