4. CircuitBreaker 状态机详解:CLOSED、OPEN、HALF_OPEN 状态转换与滑动窗口原理

熔断器的核心是一个三态状态机,配合滑动窗口统计实现自动故障隔离与恢复。理解状态转换的触发条件和滑动窗口的数据结构,是调优熔断参数的前提。

4.1 三态状态机模型

CircuitBreaker 在 CLOSED(闭合)、OPEN(断开)、HALF_OPEN(半开) 三个状态间流转,每个状态对应不同的请求处理策略。

核心原则:CLOSED 状态正常转发请求;OPEN 状态快速失败;HALF_OPEN 状态试探性放行少量请求以验证服务是否恢复。
状态 含义 请求处理方式 进入条件
CLOSED 熔断器关闭,服务正常 正常转发请求,统计失败率 初始状态;或 HALF_OPEN 试探成功
OPEN 熔断器打开,服务被隔离 直接返回降级响应,不发起真实调用 CLOSED 状态下失败率超过阈值
HALF_OPEN 熔断器半开,试探恢复 放行少量请求,观察成功率 OPEN 状态等待超时后自动进入

4.2 状态转换流程与触发条件

状态转换由 失败率阈值、滑动窗口统计 和 等待时间 三个参数驱动。下图展示了完整的状态机流转路径:

CircuitBreaker 三态状态机转换图 CircuitBreaker 三态状态机转换图 CLOSED 正常转发请求 OPEN 快速失败降级 HALF_OPEN 试探性放行 失败率 ≥ 阈值 等待超时 试探成功 → 恢复闭合 试探失败 状态转换关键参数 • CLOSED→OPEN:滑动窗口内失败率 ≥ failureRateThreshold(默认 50%) • OPEN→HALF_OPEN:等待时间 ≥ waitDurationInOpenState(默认 60 秒) • HALF_OPEN→CLOSED/OPEN:试探请求成功率决定最终状态

4.3 滑动窗口原理与统计机制

滑动窗口是熔断器判断失败率的 数据基础。Resilience4j 支持两种窗口实现:基于计数 和 基于时间。

4.3.1 基于计数的滑动窗口

  • 固定窗口大小(如 10 次调用),每次新请求入队,最旧请求出队。
  • 窗口填满后才开始计算失败率,避免冷启动阶段误判。
  • 适合调用频率稳定的场景。

4.3.2 基于时间的滑动窗口

  • 将时间划分为多个桶(bucket),每个桶统计一个时间片的调用数据。
  • 滑动窗口覆盖最近 N 个桶,滚动聚合失败率。
  • 适合调用频率波动较大的场景,能更快响应突发故障。
特性 基于计数窗口 基于时间窗口
窗口定义 固定调用次数 固定时间长度
数据粒度 单次调用 时间桶(如 1 秒)
内存开销 低(仅存储调用结果) 中(需维护桶数组)
适用场景 调用频率稳定 调用频率波动大
冷启动问题 窗口未满时不计算 首个时间桶数据稀疏

4.4 滑动窗口数据结构与计算过程

下图展示基于时间滑动窗口的内部结构,以 5 个桶、每个桶 2 秒为例:

基于时间的滑动窗口结构图 基于时间的滑动窗口结构(5 桶 × 2 秒) 桶 0 T0~T2 桶 1 T2~T4 桶 2 T4~T6 桶 3 T6~T8 桶 4 T8~T10 滑动窗口范围(当前时间 T9,覆盖 T0~T10) 失败率计算示例 窗口内总请求 = 桶0~桶4 请求数之和 | 总失败 = 桶0~桶4 失败数之和 | 失败率 = 总失败 / 总请求
调优建议:在 Spring Boot 中配置 resilience4j.circuitbreaker.configs.default.sliding-window-size=10 和 sliding-window-type=COUNT_BASED。对于高并发服务,推荐使用 TIME_BASED 并设置 minimum-number-of-calls=5 避免冷启动误熔断。

4.5 状态转换与滑动窗口的联动关系

滑动窗口为状态机提供 实时统计数据,状态机根据统计结果驱动转换:

  1. CLOSED 状态:每次调用完成后,将结果写入滑动窗口。窗口内失败率 ≥ failureRateThreshold 且调用次数 ≥ minimumNumberOfCalls 时,状态切换为 OPEN。
  2. OPEN 状态:滑动窗口暂停写入,所有请求直接降级。计时器开始计算 waitDurationInOpenState。
  3. HALF_OPEN 状态:放行 permittedNumberOfCallsInHalfOpenState 个请求,结果写入一个临时窗口。若全部成功则切回 CLOSED,否则切回 OPEN 并重置等待计时器。
常见误区:滑动窗口大小设置过小(如 3~5)会导致熔断器对瞬时抖动过于敏感,频繁误熔断。建议生产环境至少设置为 10~20,配合 slow-call-rate-threshold 慢调用率阈值一起使用。

4.6 关键参数速查表

参数名 默认值 作用 调优方向
sliding-window-size 100 滑动窗口大小(次数或秒数) 根据 QPS 调整,越大越平滑
sliding-window-type COUNT_BASED 窗口类型:计数/时间 高并发用 TIME_BASED
failure-rate-threshold 50 失败率阈值(百分比) 核心服务设 30,非核心可设 60
wait-duration-in-open-state 60s 熔断后等待恢复时间 根据故障恢复时长调整
permitted-number-of-calls-in-half-open-state 10 半开状态试探请求数 不宜过大,避免压垮恢复中的服务
minimum-number-of-calls 100 滑动窗口最小统计基数 防止冷启动误判

4.7 实战配置示例

以下是一个面向高并发订单服务的熔断器配置,使用基于时间的滑动窗口:

resilience4j.circuitbreaker:
  configs:
    default:
      sliding-window-type: TIME_BASED
      sliding-window-size: 10
      minimum-number-of-calls: 5
      failure-rate-threshold: 40
      slow-call-rate-threshold: 50
      slow-call-duration-threshold: 2000ms
      wait-duration-in-open-state: 30s
      permitted-number-of-calls-in-half-open-state: 3
  instances:
    orderService:
      base-config: default

该配置中,滑动窗口覆盖最近 10 秒,至少统计 5 次调用后才计算失败率。失败率超过 40% 或慢调用率超过 50% 时触发熔断,等待 30 秒后进入半开状态,试探 3 个请求决定是否恢复。