触发条件一:错误率阈值
错误率阈值,说白了就是“失败多少次就拉闸”。
这是熔断降级最基础、也最常用的触发条件。你想想,一个服务不断报错,还继续放流量过去,那不是给用户喂屎吗?所以我们要定一个红线,一旦错误比例超过这个值,立刻打开熔断开关。
1.1 错误率怎么算?
先别急着定阈值,得把“错误率”的定义搞明白。在我接触过的项目里,最常见的方式是:
- 错误次数 / 请求总数——简单直接,但容易被突发小流量带偏。比如1秒内就2个请求,1个失败,错误率50%,但其实样本太小,不具备代表性。
- 滑动窗口内的错误率——比如统计最近10秒内的请求,或者最近1000个请求。这是工业界的标准做法。我习惯用时间窗口+最小请求量双重条件,避免“毛刺”误触发。
核心公式(以滑动窗口为例):
错误率 = 窗口内失败请求数 / 窗口内总请求数 × 100%
触发条件:错误率 >= 阈值(如 50%)
且 窗口内总请求数 >= 最小请求量(如 10次)
为什么还要加最小请求量?我记得有一次线上排查,一个接口平时流量很小,某次健康检查刚好赶上重启,单个失败让错误率冲上100%,直接熔断了。后来加了“至少10个请求才统计”的约束,这种误判再没出现过。
1.2 滑动窗口的两种实现
我自己常用的是计数滑动窗口和时间桶滑动窗口。给你做个对比:
| 实现方式 | 思路 | 优势 | 劣势 |
|---|---|---|---|
| 计数滑动窗口 | 固定记录最近 N 次请求的状态 | 内存固定,实现简单 | N 较小时容易丢失时间信息 |
| 时间桶滑动窗口 | 把时间切成小桶(如每1秒),统计每个桶内的成功/失败 | 能精准反映时间分布,抗突发 | 需要定期清理过期桶,内存稍大 |
曾经有个支付项目,用了计数滑动窗口,结果因为接口瞬时失败集中在1秒内,后面9秒又全是成功,错误率被稀释了。换成时间桶后,那1秒的失败率直接飙到80%,熔断立刻生效,避免了雪崩。这里要注意:时间粒度太粗会掩盖问题,太细则容易毛刺。我个人习惯用 10 秒窗口,桶大小 1 秒。
1.3 阈值怎么设?
没有一本书能告诉你“所有服务都设50%”。我的经验是分场景:
- 关键核心链路(如下单、支付):阈值设低一点。我一般 20% ~ 30%。因为这些链路出问题直接影响收入,宁可错杀一千,不可放过一个。
- 非核心查询接口:可以宽松到 50% ~ 70%。偶尔失败没关系,用户刷新一下就行。
- 依赖外部第三方:第三方稳定性你没法控制。我习惯设 40% 左右,再配合超时熔断一起用。
小技巧:在生产环境可以先设一个“只告警不熔断”的观察期。比如阈值设成 30%,但熔断开关先不开启,只记录日志。观察一周,看看实际错误率分布,再微调阈值。我曾在三个项目里都是这么调的,一次都没踩坑。
1.4 错误分类:你真的该记它为失败吗?
嗯,这里要注意:不是所有异常响应都算“错误”。我们得区分:
- 应计入错误的:HTTP 5xx、RPC 超时、线程池拒绝、业务异常(如库存不足但已经明确是服务端逻辑错误)。
- 不应计入的:客户端参数错误(4xx)、请求被限流但限流属于主动保护不算错误、健康检查的单独探测。
我曾经犯过一个错:把所有业务异常都算进去了。结果因为某个接口经常返回“余额不足”的业务错误(其实是正常逻辑),错误率一直很高,熔断反复开关。后来把业务异常和系统异常分开统计,阈值只盯系统异常,总算清净了。
警告:如果熔断器把4xx也算作失败,用户随便发个恶意请求就能让整条链路熔断——这等于把熔断开关拱手让人。务必在统计层过滤干净。
1.5 什么时候恢复?
错误率阈值触发的熔断,恢复不是立刻重置错误计数器。我见过的典型策略:
- 半开试探:熔断后,经过一个冷却时间(如 5 秒),允许少量请求通过。如果这些请求全部成功,则关闭熔断;如果又有失败,则继续熔断。
- 滑动窗口清零:关闭熔断后,清空旧的错误计数窗口,重新统计。否则历史错误会持续影响新窗口。
- 恢复阈值:有时会设置一个“恢复错误率阈值”,比触发阈值更低。比如触发是 50%,恢复条件是最近 10 个请求错误率低于 20%。用恢复阈值能防止“边缘震荡”。
我记得一个社交 app 的推送服务,恢复了熔断后因为旧窗口还没过期,很快又触发熔断。加上“恢复时清空窗口”后,抖动减少很多。
1.6 流程图:错误率熔断决策
1.7 避坑指南
最后聊几个我踩过的坑:
- 阈值设得太死板:比如所有接口统一50%,结果有的接口正常错误率就40%,稍微抖动就误熔断。我后来改为按接口维度配置,在配置中心配成“/pay/order → 30%, /search/product → 60%”。
- 忽略流量不均:某个接口白天流量大,错误率平稳;半夜流量小,一个失败就把错误率拉高。解决方法就是加最小请求量限制,比如“至少20个请求才统计”。
- 恢复得太快:冷却时间设成1秒,结果半开试探又失败,又熔断,高频振荡。我建议冷却期至少5秒,试探请求数不超过总请求的1%。
- 没有记录熔断原因:只记录“熔断”不记录“因错误率50%熔断”,事后排查时一脸懵。加上标签,比如
cause=error_rate, value=0.52,对定位非常有帮助。
一个小建议:如果团队刚引入熔断,先只对非核心接口生效。运行两周后观察误触率,再逐步铺开。别上来就给生产环境放“大杀器”,容易把自己玩崩。