微服务中的熔断与降级
1. 为什么需要熔断与降级?
在微服务架构中,一个请求往往需要经过多个服务:
用户 → 服务 A → 服务 B → 服务 C
正常情况下,各个服务能够快速响应,请求可以正常完成。
但如果服务 C 出现故障:
A → B → C ❌
B 调用 C 时可能会长时间等待,随着请求不断进入,大量请求会堆积在 B 中,占用线程、连接等资源。
C 故障
↓
B 大量请求等待 C
↓
B 线程等资源逐渐耗尽
↓
B 无法继续处理请求
↓
A 又开始等待 B
↓
A 也逐渐不可用
↓
整个调用链不可用
这种由于一个服务故障,最终导致多个服务被逐渐拖垮的现象称为:
服务雪崩(Service Avalanche)。
因此,微服务中需要通过熔断、降级等机制避免故障继续扩散。
2. 什么是熔断?
熔断(Circuit Breaker):
当系统发现某个下游服务持续异常时,暂时停止对该服务的调用,让请求快速失败,避免调用方因为不断等待而被一起拖垮。
例如:
正常:
A → B → C
C 持续发生异常:
B → C ❌
B → C ❌
B → C ❌
B → C ❌
当失败率达到一定阈值后,熔断器打开:
A → B ──X──→ C
此时新的请求不会继续访问 C,而是直接失败或者进入降级逻辑。
熔断解决什么问题?
主要解决:
“下游服务已经明显出现问题,还要不要继续调用它?”
答案是:
连续大量失败
↓
触发熔断
↓
暂时停止调用
↓
快速失败
↓
保护当前服务
这样可以防止线程等资源被大量无效请求占用,避免故障继续向上游传播。
3. 什么是降级?
降级(Fallback):
当某个服务无法正常提供功能时,放弃原本完整的业务逻辑,返回一个可以接受的兜底结果,从而保证系统的基本可用性。
例如商品详情需要查询库存:
商品服务
↓
库存服务
↓
库存:100
如果库存服务挂了:
商品服务
↓
库存服务 ❌
没必要让整个商品页面直接报错:
500 Internal Server Error
可以执行降级策略:
商品名称:iPhone
价格:5999
库存:暂时无法查询
这里的:
库存:暂时无法查询
就是一种兜底数据,也经常称为:
Fallback
再比如推荐服务出现故障:
正常:
根据用户兴趣返回个性化推荐
降级:
直接返回热门商品
虽然功能没有正常情况下那么完整,但系统至少还能继续使用。
4. 熔断和降级有什么区别?
可以用一句话理解:
熔断决定“还调不调用”,降级决定“调用不了以后返回什么”。
例如:
B → C
发现 C 连续发生大量异常:
B → C ❌
B → C ❌
B → C ❌
触发:
熔断
↓
B ──X──→ C
之后执行:
降级
↓
返回 fallback 数据
所以两者经常配合使用:
下游服务发生故障
↓
达到熔断条件
↓
熔断
↓
暂时停止调用下游
↓
执行降级逻辑
↓
返回兜底数据
5. 什么时候需要使用?
熔断和降级主要用于分布式、微服务、远程调用等可能发生服务依赖的场景。
例如:
订单服务 → 商品服务
订单服务 → 库存服务
订单服务 → 支付服务
商品服务 → 推荐服务
尤其是以下场景:
① 下游服务发生大量异常
例如:
订单服务 → 库存服务 ❌
如果库存服务已经连续大量失败,可以进行熔断,避免继续发送大量无意义请求。
② 下游服务响应特别慢
服务虽然没有直接报错,但是一次请求需要:
正常:50ms
异常:5s、10s、30s
大量请求长期等待同样可能耗尽线程等资源,因此慢调用达到一定比例后也可以触发熔断。
③ 非核心功能出现故障
例如商城中的:
个性化推荐
广告
排行榜
猜你喜欢
这些功能出现问题时,通常没必要让整个商城不可用。
因此可以直接进行降级:
推荐服务异常
↓
返回默认热门商品
核心思想就是:
牺牲部分非核心功能,保证核心系统可用。
6. 如何使用?
在实际的 Java 微服务项目中,一般不会自己手写完整的熔断器,而是使用现成的服务治理组件,例如:
Sentinel
Resilience4j
以 Sentinel 的思想为例,可以为某个远程调用配置熔断规则:
订单服务
↓
调用库存服务
↓
Sentinel 统计调用情况
↓
失败率 / 慢调用达到阈值
↓
触发熔断
↓
暂时停止调用库存服务
↓
执行 fallback / 降级逻辑
例如伪代码:
public Stock getStock(Long productId) {
try {
return stockService.getStock(productId);
} catch (Exception e) {
return fallback(productId);
}
}
public Stock fallback(Long productId) {
return new Stock("库存暂时无法查询");
}
真实项目中会交给 Sentinel、Resilience4j 等组件完成熔断判断,而开发者主要负责:
配置熔断规则
+
编写降级 / fallback 逻辑
7. 最终总结
微服务中:
A → B → C
如果 C 出现故障而没有保护措施:
C 故障
↓
B 请求堆积
↓
B 资源耗尽
↓
B 故障
↓
A 请求堆积
↓
A 故障
↓
服务雪崩
加入熔断降级以后:
C 持续故障
↓
触发熔断
↓
B 暂时停止调用 C
↓
执行降级逻辑
↓
返回 fallback 兜底数据
↓
B 保持可用
↓
避免故障继续扩散
因此可以记住:
熔断:下游已经连续出问题,暂时不调用它。
降级:正常功能无法使用,返回一个可以接受的兜底结果。
最终目的:防止服务雪崩,牺牲局部功能,保证整个系统尽可能可用。