熔断、隔离、限流与降级:四种机制分别阻断什么故障
区分熔断状态、并发隔离、请求准入和降级结果,建立半开探测、资源预算与恢复放量模型。
Spring Cloud CircuitBreaker 提供统一 factory 抽象;具体状态窗口由实现决定。参见 Spring Cloud Circuit Breaker 与 Resilience4j。
四种机制解决四个不同问题
限流在工作开始前控制进入速率或并发,保护本服务与下游容量;隔离用独立线程池、信号量或连接池限制某个依赖占用共享资源;熔断根据近期结果在一段时间内快速拒绝已知不健康依赖;降级决定被拒绝或失败后向业务返回什么。把四者都叫“熔断降级”会让配置和指标无法解释。
策略必须按依赖与操作粒度隔离。查询库存与扣减库存风险不同,支付查询与支付提交不能共享一个 circuit。粒度过细会产生高基数和稀疏样本,粒度过粗又让低价值慢接口拖垮关键写入。通常以 serviceId + operation class 建立有限治理目录。
Circuit Breaker 是采样状态机
CLOSED 收集调用结果,失败率或慢调用率达到阈值后进入 OPEN;等待窗口后进入 HALF_OPEN,只允许有限探测;探测满足条件才关闭,否则重新打开。最小调用数、滑动窗口类型、慢调用阈值和异常分类共同决定灵敏度。没有最小样本时,一次失败就熔断会制造抖动。
业务拒绝、权限错误和参数错误不应计作依赖故障;超时、连接失败和服务器过载才可能进入失败统计。fallback 本身也要限时和隔离,不能在主依赖失败后同步调用另一个同样脆弱的依赖。半开探测必须限制并发,防止所有实例同时向刚恢复的下游发洪峰。
降级是业务产品决策
商品推荐可以返回带年龄的缓存结果,排行榜可以暂时关闭,支付状态未知却不能返回“支付成功”。降级响应要显式标记 degraded、source 与 dataAge,调用方才能选择展示、重试或阻止后续动作。默认空集合会把依赖故障伪装成真实无数据。
恢复要观察拒绝率、在途数、下游尾延迟和成功探测,并逐步增加流量。只看 circuit 回到 CLOSED 就全量放开,会把尚未恢复容量的依赖再次击穿。治理配置变更也要版本化、灰度和自动回收。
把同步调用画成预算递减的状态机
设计时为每条边记录 owner、协议、连接模型、超时阶段、重试责任、幂等键、流量上限、降级语义和回滚方式。同步扇出越大,成功率乘积越低,尾延迟取最大值;能异步解耦的非关键副作用不要停留在主请求链。
失败控制必须按依赖隔离
注册中心不可用、无实例、连接池满、连接失败、读取超时、业务拒绝和服务端错误要分型。只有动作未开始或有幂等保障的暂态失败允许重试;结果未知先查询或使用稳定幂等键。限流、隔离和熔断的拒绝应成为可观测结果,不能统一包装成空数据。
隔离资源要与真实瓶颈对齐
线程池舱壁能隔离阻塞调用的线程与队列,信号量舱壁限制同步并发但不搬移执行线程,响应式链路通常用并发许可而不是额外线程池。若真正瓶颈是数据库连接,却只限制 Feign 线程,仍可能有多个入口共同耗尽数据库;隔离上限要沿资源链取最小安全预算。
排队不是免费缓冲。舱壁队列过大时,请求在开始执行前 deadline 已耗尽,随后仍占用下游造成无效工作。准入时根据剩余时间、预计服务时间和队列位置早拒绝,并为关键操作保留资源。拒绝率升高是容量信号,不能靠扩大队列消音。
用两个 Java 状态模型固定决策边界
这两个 Java 17 模型不启动真实注册中心、Gateway 或 RPC Server,而是把本篇的状态、预算和不变量转成确定输出。真实集成测试继续验证客户端协议、自动配置、连接复用、推送延迟与故障时序。
javac --release 17 -Xlint:all -Werror examples/backend-development/microservice/circuit-isolation-degrade/CircuitStateDemo.java examples/backend-development/microservice/circuit-isolation-degrade/BulkheadRateDemo.java
java -cp examples/backend-development/microservice/circuit-isolation-degrade CircuitStateDemo
java -cp examples/backend-development/microservice/circuit-isolation-degrade BulkheadRateDemostates=[CLOSED,OPEN,HALF_OPEN,CLOSED] failures=5 probes=2 recovered=true
incoming=120 permits=30 bulkheadSlots=20 admitted=20 rateRejected=90 isolatedRejected=10状态模型输出变化时,要解释对应的服务边界、Deadline、版本或治理不变量为什么改变。集成测试必须主动制造连接已写出后超时、实例列表陈旧、配置刷新一半、半开探测和灰度标签断链。
契约、安全与配置共同决定可运营性
动态配置和发现元数据都可能陈旧。变更必须带版本、owner、范围、过期时间和回滚值,先灰度到少量实例并比较版本分布。会影响线程池、连接池、路由、限流和鉴权的配置要通过不变量校验,失败时保留上一完整快照。
容量与可观测证据要覆盖控制面和数据面
上线证据包括新旧契约互调、实例排空、Deadline 传播、幂等重试、治理状态机、灰度指标和回滚后的残留任务。完成标准不是“组件控制台显示健康”,而是业务不变量保持、未知结果可查询、故障被限制在预算内并最终收敛。
