问题
下游服务变慢,调用方一直等待并不断重试,线程池被打满,故障顺着调用链往上传染,最终整站雪崩。
熔断器三状态
| 状态 | 行为 |
|---|---|
| 关闭 | 正常放行,统计失败率 |
| 打开 | 直接失败,不再打下游 |
| 半开 | 放少量请求探测是否恢复 |
失败率超阈值就「打开」,过一段冷却时间转「半开」试水;成功则回到关闭,失败则继续打开。
降级是什么
熔断后不硬等,而是返回兜底:推荐位给默认列表、非核心接口返回缓存、评论区暂时关闭。保证主流程可用,牺牲次要功能。
两个提醒
- 超时要有上限:熔断的前提是每个调用都有合理超时,否则永远卡在打开前的等待里;
- 兜底也要正确:降级返回的数据不能误导用户或引发二次错误。
实战案例:三个“熔断反而更糟”
- 熔断了但没降级:依赖失败后请求直接被拒,页面却没有任何兜底内容。熔断必须搭配降级:返回缓存、默认值或友好提示。
- 阈值太敏感:少量超时就打开熔断,正常波动下反复开合。应结合错误率、最小请求数与时窗,并设置半开探测逐步恢复。
- 级联超时没有收敛:上游超时 30 秒、每层还各自重试 3 次,一次故障被放大成雪崩。应为每层设置小于上层的超时与有限重试,并只对可重试错误重试。
常见问题(FAQ)
熔断与限流有什么区别?限流保护自己不被压垮,熔断避免持续调用已经不可用的依赖。打开后什么时候恢复?半开状态下放少量请求探测,成功率达标后再完全闭合。降级返回什么更好?优先返回可接受的旧数据或默认值,并明确标注“暂不可用”,别静默返回空。所有依赖都要熔断吗?只对可能长时间不可用的强依赖加;内部低延迟调用加了反而增加复杂度。
降级方案怎么设计才可用
熔断只是停止调用,真正决定用户体验的是降级内容。设计降级方案时,建议遵循以下原则。
- 按数据敏感度分级:核心数据不可降级,宁可明确提示失败;非核心的推荐、统计与展示类数据可以返回缓存或空值,保证主流程可用。
- 降级要显式可见:界面上应让用户知道数据可能不是最新的,而不是静默展示旧内容。静默失败会让用户基于错误信息做决策,风险更大。
- 保留手动开关:自动熔断可能出现误判,需要人工快速开关的入口。开关应支持按依赖维度而不是全局,避免一处误判导致整体降级。
- 降级路径也要测试:很少使用的分支最容易在真正需要时失效,应把降级开关纳入常规测试,并定期演练一次。
- 记录降级时长与频次:把降级事件作为指标上报,长期频繁降级说明依赖本身不稳定,需要从根因解决而不是长期忍受。
与容量策略的配合
熔断解决依赖不可用,限流保护自身不被压垮,二者应当配合使用。只做熔断时,突发流量仍可能打满自身资源;只做限流时,不可用的依赖仍会被持续调用。把两种策略按依赖维度配置,系统在压力下的表现会稳定得多。
多依赖场景下的优先级
当多个依赖同时异常时,系统应按业务价值决定保留哪些能力:优先保证下单、支付等核心链路,先降级推荐与统计。提前定义好优先级,故障时就不必临时争论先救哪一个,也能让降级策略在代码中保持简单。