Back to Javaguide

降级&熔断详解

docs/high-availability/fallback-and-circuit-breaker.md

latest17.7 KB
Original Source

什么是降级?

服务降级(Service Degradation)是从系统功能优先级视角应对故障的策略:在负载(如 CPU 使用率 > 80%、线程池饱和、响应时间 P99 > 1s)接近阈值时,有策略地降低非核心服务质量,释放资源确保核心路径可用性。

降级的特征

维度说明示例
触发原因整体负荷超出阈值CPU 使用率 > 80%、P99 RT > 1s、P999 RT > 3s、队列积压深度 > 容量 80%
目的保核心、弃非核心关闭推荐、保留下单
粒度服务/页面/接口/功能三级关闭商品推荐模块
可控性配置中心动态开关Nacos 2.0+ gRPC 长连接(毫秒级推送)
优先级1-10 级,从外围到核心L10:下单 > L5:评论 > L1:推荐

降级方式有哪些?

方式说明适用场景失败路径与风险
延迟服务将非实时操作异步化,写入 MQ/缓存评论积分、数据统计MQ 积压需背压(如 Jitter 重试避免风暴)
页面片段降级直接关闭非核心功能区块推荐区、广告位
异步请求降级页面内异步加载接口返回兜底数据配送至、价格预测兜底数据需预加载缓存
页面跳转降级将流量导流到静态/简版页面静态活动页、维护页需预设静态页版本
写降级优先写入 Redis/本地 WAL,通过可靠 MQ 或定时任务同步 DB秒杀库存扣减需保证最终一致性(对账/补偿);内存队列在节点宕机时会丢失数据
读降级只读缓存,屏蔽后端调用商品详情读多写少缓存穿透时需返回降级页

降级开关实现方案

方案实时性一致性复杂度适用场景
配置文件 + 重启非紧急、不频繁变更
数据库开关表需要审计日志的场景
配置中心(Nacos 2.0+ / Apollo)高(毫秒级推送)最终一致(gRPC 双向流)生产环境推荐
Redis/Diamond最终一致轻量级方案

注:Nacos 2.0+ 基于 gRPC 持久长连接(Persistent Connection)和双向流(Bidirectional Streaming)实现服务端主动推送,推送生效时间达毫秒级。与 1.x 的 HTTP 长轮询(Polling)相比,gRPC 模式避免了重复 TPS,利用 NIO 机制提升吞吐量,整体性能提升约 10 倍,内存占用降低 50%,单机可支撑 10W+ 实例连接。

一致性机制:Nacos 2.0+ 并非采用严格的 ACK 机制,而是依赖 HTTP/2 PING 帧(Keepalive)检测连接健康和快速感知断开,确保推送可靠。连接丢失时客户端自动重连并同步数据实现最终一致收敛。

网络分区场景:Nacos 的注册中心(Naming)模块偏向 AP,但配置中心(Config)模块基于 Raft 协议保证强一致性(CP)。降级开关属于配置中心范畴,发生网络分区时,处于少数派(Minority)的 Nacos 节点将拒绝写入并可能导致客户端配置漂移。此时客户端需依赖本地缓存文件(Failover 配置)作为最终兜底,并忍受降级规则无法实时推送的风险。

升级兼容性:Nacos 2.0 服务器兼容 1.x 客户端(通过 HTTP 协议),但 2.0 客户端不兼容 1.x 服务器(gRPC 协议)。

客户端线程管理注意:gRPC 执行器核心线程数基于 CPU 核数配置(如 200 核心、800 最大),需注意避免资源耗尽。

服务降级有哪些分类?

降级按照是否自动化可分为:

  • 自动开关降级(超时、失败次数、故障、限流)
  • 人工开关降级(秒杀、电商大促等)

自动降级分类:

类型触发阈值兜底方案失败路径要求
超时降级RT > 阈值(如 P99 > 500ms)且持续 N 次默认值需幂等性保护,避免重试风暴
失败降级异常率 > 阈值(如 50%)兜底数据兜底数据需预热缓存
故障降级HTTP 5xx/RPC 异常/DNS 解析失败缓存数据缓存未命中时返回默认值
限流降级QPS > 阈值排队页/无货/错误页排队页需防重入(幂等令牌)

重试风暴:当服务恢复但大量客户端同时重试时,可能导致服务再次崩溃。防御措施包括:Jitter 重试(随机退避)、令牌桶限流、分组分批恢复。

大规模分布式系统如何降级?

在大规模分布式系统中,经常会有成百上千的服务。在大促前往往会根据业务的重要程度和业务间的关系批量降级。

降级平台能力

大型互联网公司通常会有统一的降级平台,核心能力包括:

能力说明实现要点
分级管理1-10 级服务优先级核心业务评审、依赖关系梳理
批量降级按级别/分组批量执行降级顺序编排、原子性保证(二阶段提交)
动态开关配置中心实时推送Nacos 2.0+ gRPC 或 WebSocket
效果验证灰度验证 + 监控观测A/B 测试、指标对比
一键回滚版本管理 + 快速回滚配置版本化、变更审计

降级预案制定

  1. 业务分级:梳理服务核心度,定义 L1-L10 优先级
  2. 依赖分析:绘制服务调用链,识别关键路径和单点依赖
  3. 降级策略:为每个非核心服务设计降级方案(含失败路径)
  4. 演练验证:定期进行降级演练,确保预案有效性(含网络分区场景)

网络分区场景:依据 PACELC 定理,分区时需权衡可用性(A)与一致性(C)。降级预案应明确分区期间的行为模式(如继续服务本地缓存、暂停跨区调用)。

详细介绍: CAP & BASE理论详解

什么是熔断?

熔断器模式(Circuit Breaker Pattern)是应对微服务雪崩效应的一种链路保护机制,类似电路中的保险丝。

雪崩效应

正常调用链路:服务 A ──> 服务 B ──> 服务 C

雪崩场景:

  • 服务 C 响应变慢/不可用
  • 对服务 C 的调用排队(线程池耗尽)
  • 服务 B 的调用线程阻塞
  • 服务 A 也被拖垮,雪崩扩散到整个系统

熔断器状态机

熔断器包含三种状态:

状态说明行为状态转换条件
Closed(关闭)正常状态,允许请求通过记录失败率/慢调用比例失败率/慢调用比例 > 阈值 → Open
Open(打开)熔断触发,拒绝请求快速返回 Fallback,不再调用下游经过冷却时间(sleepWindow,如 10s) → HalfOpen
HalfOpen(半开)探测服务是否恢复释放配置数量(如 3 个)的探路请求所有探测成功(或满足成功率阈值)→ Closed;任一失败 → Open

Half-Open 风险与 Warm Up 预热:探测请求可能触发重试风暴或二次雪崩。建议限制探测请求数(如 Sentinel 默认 3 个),并要求所有探测成功(或满足配置的成功率阈值)才转为 Closed。若放行条件过于宽松(如单次成功即 Closed),面对刚从宕机中拉起的冷节点,瞬间涌入的并发流量会直接打满线程池,造成二次击穿(冷启动杀手)。

Warm Up 预热机制:需配合基于令牌桶/漏桶算法的预热限流,按照冷却因子(默认 3)在预热周期内(如 10s)将放行 QPS 阈值从 maxQps / 3 平滑拉升至最大容量,防止冷节点由于 CPU Cache Miss 和数据库连接池未初始化被二次击穿。监控冷启动期间的 P99 延迟数据库连接池活跃连接数 以验证预热效果。

熔断策略

Sentinel 1.8.2+ 支持三种熔断策略:

策略触发条件典型阈值配置版本要求
慢调用比例P99 RT > 最大慢调用 RT 且比例 > 阈值RT > 500ms,比例 > 50%1.8.0+
异常比例异常比例 > 阈值异常率 > 50%全版本
异常数异常数 > 阈值1 分钟内异常 > 50全版本

P99 vs 平均 RT:使用平均 RT 可能掩盖长尾延迟。生产环境建议监控 P99/P999,避免"大部分请求快但少数请求极慢"的场景。

降级和熔断有什么区别?

维度降级熔断
核心关注资源优先级分配调用链路保护
触发方式主动(系统/人工)被动(依赖异常触发)
作用范围当前服务或下游调用链的上游
恢复方式手动关闭或自动检测自动(Half-Open 探测)
返回内容兜底值/缓存/静态页面Fallback 方法

三者关系

  • 限流:保护自身不被打垮(限制进入流量)
  • 降级:自身主动牺牲非核心功能(降低服务质量)
  • 熔断:防止被下游拖垮(切断异常依赖)

比喻:限流是"限流进入商场的客流",降级是"商场关闭部分楼层",熔断是"发现供应商出问题后停止与其合作"。

有哪些现成解决方案?

Spring Cloud 生态中常用的熔断降级组件:

  • Hystrix 1.5.18(2018 年停止维护)
  • Sentinel 1.8.2+(阿里开源,推荐)
  • Resilience4j 1.7.1+(轻量级)
  • Spring Retry(重试组件)

Hystrix vs Sentinel vs Resilience4j

维度Sentinel 1.8.2+Hystrix 1.5.18Resilience4j 1.7.1+
维护状态✅ 活跃维护❌ 2018 年停止维护✅ 活跃维护
隔离策略并发线程数隔离(信号量)线程池隔离(默认)/ 信号量SemaphoreBulkhead / FixedThreadPoolBulkhead
熔断策略慢调用比例/异常比例/异常数异常比例异常比例/异常数
实时指标滑动窗口滑动窗口(RxJava)环形缓冲
限流QPS/并发线程/调用关系有限支持RateLimiter
流量整形慢启动/匀速排队
系统自适应保护✅ Load/RT/线程数/QPS
控制台✅ 开箱即用⚠️ 简陋⚠️ 需自行搭建
框架适配Servlet/Spring Cloud/Dubbo/gRPCSpring Cloud NetflixReactor/Vert.x

隔离策略对比

策略SentinelHystrixResilience4jTrade-offs
线程池隔离-✅ 默认✅ FixedThreadPoolBulkhead优势:超时控制独立、资源隔离彻底、支持异步
劣势:OS 级别上下文切换开销(P99 恶化)、线程池大小难确定、增加 GC 压力
信号量隔离✅ 轻量级、无线程切换✅ 轻量级✅ SemaphoreBulkhead优势:无额外线程开销、内存占用小
劣势:不能做超时控制(依赖业务层)、不支持异步

GC 与调度压力:线程池隔离会创建大量独立线程。在高并发下,真正的瓶颈在于 CPU 在海量线程间进行 OS 级别的调度唤醒与挂起。这种频繁的上下文切换 会无谓消耗大量 CPU 的 Us/Sy 时间,并直接导致业务请求的 P99 尾延迟急剧恶化。锁争用仅是并发争用的表象,真正的杀手是线程调度开销。Resilience4j 的 FixedThreadPoolBulkhead 基于 ArrayBlockingQueue,极高并发下也存在锁争用,但相比上下文切换开销通常次要。

系统自适应保护(Sentinel 独有)

Sentinel 1.8+ 提供系统自适应保护(System Rule),其核心是引入类似 TCP BBR 的动态容量评估逻辑:

隐性核心条件当前并发线程数 > (系统最大 QPS × 最小 RT)

指标说明典型阈值版本要求
Load(系统负载)Linux load1> CPU 核数 × 2全版本
平均 RT所有入口流量的平均响应时间> 500ms(建议用 P99)1.8.0+ 支持 P99
并发线程数当前并发线程数> 500全版本
入口 QPS入口流量的 QPS> 1000全版本

触发后,系统会自动拒绝部分请求,避免系统崩溃。相比静态阈值,BBR 风格的动态容量评估能防止静态阈值滞后导致的系统崩溃。

选型建议与迁移 Trade-offs

场景推荐方案迁移 Trade-offs
新项目(Spring Cloud Alibaba)Sentinel 1.8.2+无迁移成本
新项目(响应式/轻量级)Resilience4j 1.7.1+需自行实现控制台
存量项目(Hystrix)继续使用 Hystrix,规划迁移迁移成本:API 变更 + 控制台搭建 + 规则迁移
需要系统自适应保护Sentinel(独有)无替代方案

推荐阅读

参考

<!-- @include: @article-footer.snippet.md -->