服务雪崩怎么防止?
更新时间:2026-09-18。问题驱动短答页。雪崩不是某台机器挂了,而是一个慢依赖把整条调用链的线程全部拖死。
一句话回答
雪崩根因是「同步调用下,慢下游长期占住上游线程不释放」,线程池耗尽后健康接口也无法服务。防护是六件套组合:超时、有限重试、熔断、降级、隔离、限流——用超时止血、熔断给故障下游喘息、fallback 兜底、舱壁隔离把故障关在单间、限流保核心链路。
防护六件套
| 手段 | 作用 | 关键点 |
|---|---|---|
| 超时 | 不让请求无限等 | 每次远程调用都设;上游超时略 > 下游 |
| 重试 | 扛偶发抖动 | 仅幂等读、1~2 次 + 退避,否则放大流量 |
| 熔断 | 下游持续故障时不再猛打 | closed/open/half-open,按错误率/慢调用比例触发 |
| 降级 fallback | 失败时给兜底结果 | 返回缓存/默认值,不能再调慢服务 |
| 隔离(舱壁) | 一个依赖不占光全部线程 | 线程池隔离(慢依赖)/信号量隔离(快调用) |
| 限流 | 超过容量直接拒绝排队 | 网关 + 应用双层,保核心、弃边缘 |
熔断器三态
bash
Closed(正常放行+统计)
│ 失败率/慢调用比例超阈值
▼
Open(直接快速失败、不调下游,走 fallback)
│ 冷却时间到
▼
HalfOpen(放少量探测请求)
├─ 成功 → Closed(恢复)
└─ 失败 → Open(继续冷却)半开只放少量请求,避免下游刚恢复就被全量流量再次压垮。
落地要点
- 超时是地基:不设超时,熔断和隔离都来不及生效,线程已被挂死。
- fallback 要「干净」:降级逻辑里再去查可能挂的库/服务等于没降级;用本地缓存或静态默认值。
- 隔离按依赖分池:调推荐、调库存、调支付用不同线程池,推荐服务慢不应拖垮下单。
- 降级分级:大促时关评价、推荐、广告等非核心,保交易、支付主链。
- 框架选择:新系统用 Resilience4j(轻量),要成熟流控控制台用 Sentinel,Hystrix 已停更仅存量维护。
坑
- 只熔断不隔离:遇到「不报错但极慢」的下游,错误率没上去、迟迟不熔断,靠慢调用比例阈值和线程池隔离兜底。
- 重试不设退避、对写接口重试:故障期形成重试风暴,或造成重复扣款(要配幂等)。
- 半开放行太多:下游刚恢复又被压垮,在 open/half-open 间反复震荡。
- 阈值太灵敏:正常抖动也频繁误熔断,阈值要高于日常波动并设最小调用数。
完整状态机、Hystrix/Resilience4j/Sentinel 对比与配置见 服务熔断、降级与隔离;从容量源头减负见 高并发系统设计;与 Redis 缓存雪崩(另一概念)的区别见 Redis 雪崩和穿透有什么区别。
总结
防服务雪崩要认清它是慢下游经同步等待占满上游线程池引发的级联耗尽,靠「超时(上游略宽于下游)+ 幂等接口有限退避重试 + 熔断器按错误率和慢调用比例在 closed/open/half-open 间切换 + 不依赖慢资源的 fallback 降级 + 按依赖划分线程池/信号量的舱壁隔离 + 网关和应用双层限流」六件套组合,半开只放少量探测防二次压垮、fallback 用缓存默认值、降级分级保核心链路,框架上新系统选 Resilience4j、要控制台选 Sentinel,并注意区分它与 Redis 缓存雪崩是两个不同概念。