C# Polly策略使用方法 C#如何实现Http请求的重试和熔断

来源:这里教程网 时间:2026-02-21 17:39:35 作者:

重试策略怎么配才不卡死请求

默认的

RetryPolicy
不设超时或重试间隔,容易让请求卡住几秒甚至更久。必须显式控制重试次数、退避方式和总耗时上限。

WaitAndRetryAsync
配合指数退避(如
Backoff.DecorrelatedJitterBackoffV2
),避免下游雪崩式重试
HttpClient
外层加
CancellationToken
,并传给
ExecuteAsync
,防止策略内部无限等待
别只靠重试次数限制——加上
TimeSpan.FromMilliseconds(3000)
这类硬性超时,否则网络卡顿时策略会等满所有重试周期
示例中常见错误:把
HttpRequestException
TaskCanceledException
混在一起重试,其实后者大概率是上游已取消,再试没意义

熔断器触发后为什么还在发请求

CircuitBreakerPolicy
默认只对异常类型生效,HTTP 200 但业务返回
{"code":500}
这类“假成功”不会触发熔断,得手动判断响应内容。

AdvancedCircuitBreakerAsync
,配合自定义
shouldHandle
函数,检查
response.IsSuccessStatusCode == false
或解析 JSON 后判断
responseContent.code != 0
熔断状态不是全局共享的——每个
HttpClient
实例或每个策略实例独立维护状态,别误以为配置一次就全应用生效
注意
failureThreshold
是“失败比例”,不是绝对次数;比如设 0.5,意味着最近 10 次里有 5 次失败才会熔断,不是第 5 次就跳闸
熔断后调用会直接抛
BrokenCircuitException
,不是静默失败,要确保上层有捕获逻辑,否则可能引发未处理异常崩溃

如何把重试 + 熔断串成一条链

不能简单 new 两个策略然后分别调用——必须用

PolicyWrapAsync
组合,否则熔断器收不到重试后的最终结果,无法准确统计失败率。

顺序很重要:外层放熔断(
circuitBreaker
),内层放重试(
retry
),这样重试过程中的失败都算进熔断统计
别漏掉
Policy.WrapAsync(retry, circuitBreaker)
的括号方向,写反会导致编译通过但运行时策略不生效
组合后调用
policyWrap.ExecuteAsync(() => httpClient.GetAsync(url))
,而不是分别执行两个
ExecuteAsync
如果还加了降级(
FallbackPolicy
),它应该放在最外层,兜住熔断和重试都失败的情况

HttpClient 与 Polly 怎么共存不冲突

直接给

HttpClient
设置
Timeout
会跟 Polly 的重试逻辑打架——比如 HttpClient 内部 10 秒超时,而 Polly 重试 3 次每次等 2 秒,第三次还没发出去就被 HttpClient 自己扔异常了。

HttpClient.Timeout
设为
TimeSpan.MaxValue
,把超时控制权完全交给 Polly
每个
HttpClient
实例应绑定一个固定的策略实例(推荐用 DI 注入单例策略),不要每次请求都 new 新策略,否则熔断状态无法累积
如果用了
IHttpClientFactory
,在
AddHttpClient
里用
AddPolicyHandler
注册策略,它会自动处理生命周期和策略复用
注意
HttpRequestException
的 InnerException 可能是
SocketException
OperationCanceledException
,Polly 默认不展开 InnerException,需手动写
ex.InnerException is TimeoutException
这类判断
实际最难调的往往是熔断窗口期和失败判定粒度——比如 60 秒滑动窗口里,你希望 10 次失败就熔断,但如果请求本身很慢,这 10 次可能集中在最后 2 秒发生,导致熔断来得又急又猛,下游根本来不及恢复。这时候得结合指标监控,动态调整参数。

相关推荐