在微服务、分布式系统架构下,"服务雪崩"几乎是所有架构师和后端工程师都会面对的问题。一次偶发的慢查询、一个下游依赖的异常,就可能引发连锁反应,最终拖垮整个系统。
服务雪崩
服务雪崩是指:在分布式系统中,一个或多个下游服务出现异常(变慢、不可用),导致上游服务请求线程大量阻塞、堆积,进而上游服务也变慢甚至崩溃,最终使一系列服务都不可用的"连锁故障"现象。
典型过程:
- 某个核心服务 A 依赖多个下游服务 B、C、D。
- 由于网络抖动、DB 慢查询、GC 卡顿等原因,服务 B 响应突然变慢。
- 服务 A 发往 B 的请求线程开始大量阻塞,连接池占满、线程池打满。
- A 自身延时飙升,CPU 飙高,进而超时/失败率上升。
- 上游还依赖 A 的其他服务(如网关、其他业务服务)同样出现阻塞、资源耗尽,最终一大片服务连锁宕机。
触发因素常见有:
- 下游服务宕机或不可达(网络、机房、DNS 等)
- 下游服务响应极度变慢(慢查询、锁竞争、GC、磁盘 IO 等)
- 流量突增,超过容量上限(热点活动、恶意攻击)
- 配置错误(超时时间过长、重试次数过大等)
要想系统具备"韧性(Resilience)",就必须在架构与代码层面对"雪崩"进行防御。服务降级 与服务熔断就是关键手段。
服务降级
什么是服务降级?
服务降级指:在系统高压力、依赖不可用或故障场景下,主动降低非核心功能的服务质量,牺牲部分体验或功能,以保证核心能力可用、整体系统存活。
一句话:"宁可部分功能不可用,也要保证核心路径不死"。
典型场景
- 下游服务不可用或严重超时(比如推荐服务挂了)
- 总体 QPS 暴涨,系统即将被压垮
- 批量任务/非核心功能影响主链路
- 节假日大促、预估流量高峰期,需要预防性降级
典型策略
可以按是否可预期 和是否自动触发来划分:
(1)预案式、人工开关降级
针对重要活动或核心业务,预先设计好降级策略和"开关":
- 提前准备降级配置(如:关掉非必要查询、合并订单信息、关闭部分个性化功能)
- 通过配置中心/管理后台,一键开关降级
- 适合集中流量、高风险活动场景(双 11、大促)
(2)自动化降级(基于系统指标触发)
系统监控的关键指标达到阈值时自动触发,如:
- CPU 超过 80%
- 平均响应时间(RT)超过某个阈值
- 错误率/超时率超过一定比例
降级返回内容的设计
降级不是简单"抛异常",而是要提供可接受的退路,常见策略:
-
返回默认值或兜底文案
-
使用缓存或静态数据
-
部分字段为空、隐藏功能
服务熔断
什么是服务熔断?
服务熔断(Circuit Breaker)借鉴的是电路中的"保险丝"概念:当调用某个下游服务错误率过高时,主动短路后续请求,不再继续向下游发起真实调用,而是快速失败或走降级逻辑,以保护自己和下游服务。
目的:避免在下游已经不健康的情况下继续大量消耗资源、放大故障。
熔断器的三种状态
典型的熔断模型(如 Hystrix、Resilience4j)包含三种状态:
-
Closed(关闭)状态
- 说明当前依赖服务健康
- 所有请求正常透传到下游
- 但会持续统计调用的错误率、RT 等指标
-
Open(打开)状态
- 一段时间内错误率达到阈值(例如:10 秒内请求超过 100 次且错误率 > 50%)
- 熔断器"打开",直接拒绝请求或走降级逻辑
- 不再真正调用下游,快速失败,减轻自身与下游压力
-
Half-Open(半开)状态
- 经过一段"冷静期"(如 5 秒、10 秒)后
- 熔断器进入半开,只放行少量"探测请求"到下游
- 若探测请求成功率较高 → 认为下游恢复 → 切回 Closed
- 若继续大量失败 → 重新回到 Open,继续熔断
熔断与超时、重试的关系
- 超时控制:防止单次调用长时间占用线程,是熔断的基础。
- 重试机制:在可恢复、幂等的场景下可以适度重试,但过多重试会加剧雪崩。
- 熔断:在错误率"持续偏高"时,从整体上限制调用,防止进一步加压。
常见错误做法:
- 超时时间配置过长(例如 HTTP 客户端默认 30s)
- 重试次数太多(如同步接口自动重试 3~5 次)
- 没有熔断,导致所有服务都去死扛一个已经"挂掉"的依赖
服务降级服务熔断的区别与协同
很多人会把"降级"和"熔断"混为一谈,它们确实密切相关,但重点不同:
核心区别
| 维度 | 服务降级 | 服务熔断 |
|---|---|---|
| 出发点 | 在高压或故障场景下降低系统负载、保证核心可用 | 保护调用方和被调方,避免故障持续放大 |
| 触发依据 | 系统整体负载、手动开关、业务策略 | 特定依赖的错误率、超时率、RT 等 |
| 作用范围 | 可全局(某业务域)、也可单接口 | 通常针对"某个下游依赖" |
| 返回内容 | 一般是"降级结果"(缓存/默认值/空结果等) | 多为快速失败,但常与降级同时使用 |
| 粒度 | 更偏"业务策略级" | 更偏"技术防护级" |
简单理解:
- 熔断更像"防火墙":检测到下游不健康就断路。
- 降级更像"备用预案":当情况不佳时用次优方案维持运行。
实战中的协同方式
一个典型链路:
- 调用下游服务前,先检查是否已熔断。
- 若已熔断(Open)→ 直接走"降级处理"(本地缓存、默认值等)。
- 若未熔断(Closed/Half-Open)→ 发起远程调用。
- 调用失败或超时时,由熔断器统计错误。
- 在错误率持续高的情况下,熔断器会打开,并自动把后续请求引导到"降级逻辑"。
因此:熔断负责"何时不再调用下游",降级负责"在不调用下游时返回什么"。