熔断器三种状态详解:Closed、Open、Half-Open
熔断器(Circuit Breaker)是分布式系统中防止级联故障的关键模式。其核心在于通过有限状态机管理调用链路的状态转换,避免对已故障的服务持续无效调用。标准熔断器包含三种状态:关闭(Closed)、打开(Open)、半开(Half-Open)。理解每种状态的定义及转换条件是设计高可用系统的前提。
核心原则:熔断器不是“熔断后永久断开”,而是通过半开状态主动探测恢复时机,实现故障隔离与自动恢复的闭环。
2.1 三种状态定义与行为
| 状态 | 定义 | 调用行为 | 典型场景 |
|---|---|---|---|
| Closed(关闭) | 熔断器处于正常通行状态,所有请求直接转发给下游服务。 | 正常调用,同时统计失败率/超时率。 | 服务健康,调用成功率高于阈值。 |
| Open(打开) | 熔断器判定下游服务不可用,直接拒绝请求,快速失败。 | 请求立即返回错误(如 503),不发起实际调用。 | 失败率超过阈值,触发熔断保护。 |
| Half-Open(半开) | 熔断器在 Open 状态超时后进入试探阶段,允许有限请求通过。 | 放行少量探测请求,根据结果决定恢复或继续熔断。 | Open 状态超时到期,系统尝试恢复。 |
2.2 状态转换条件与触发机制
三种状态之间的转换由计数器、时间窗口和阈值共同驱动。下图展示了完整的转换闭环:
2.3 转换条件详细说明
2.3.1 Closed → Open(关闭 → 打开)
- 触发条件:在滑动时间窗口内(如 10s),请求失败率超过预设阈值(如 50%),且请求总数达到最小样本量(如 5 次)。
- 行为:熔断器立即切换为 Open 状态,后续请求直接快速失败,不调用下游。
- 典型配置:
# 示例:Hystrix 风格配置
circuitBreaker.requestVolumeThreshold: 5 # 最小请求数
circuitBreaker.errorThresholdPercentage: 50 # 失败率阈值
metrics.rollingStats.timeInMilliseconds: 10000 # 滑动窗口 10s
2.3.2 Open → Half-Open(打开 → 半开)
- 触发条件:熔断器在 Open 状态持续一段休眠时间(如 30s)后,自动进入 Half-Open 状态。
- 行为:允许有限数量的探测请求通过(通常为 1~3 个),其余请求仍被拒绝。
- 关键参数:
# 休眠时间与探测请求数
circuitBreaker.sleepWindowInMilliseconds: 30000 # 休眠 30s
circuitBreaker.halfOpenMaxRequests: 3 # 最多放行 3 个探测请求
2.3.3 Half-Open → Closed / Open(半开 → 关闭 / 打开)
- 恢复条件(→ Closed):所有探测请求均成功,且响应时间正常。熔断器重置计数器,回到 Closed 状态。
- 再次熔断条件(→ Open):任意探测请求失败或超时。熔断器立即回到 Open 状态,并重置休眠计时器,等待下一次 Half-Open 尝试。
- 避坑提示:探测请求的超时时间应短于正常调用超时,避免探测请求长时间挂起阻塞线程。
常见误区:Half-Open 状态不是“放行所有请求”,而是“放行少量探测请求”。如果配置的 halfOpenMaxRequests 过大,可能导致下游服务被突发流量压垮,失去熔断保护意义。
2.4 状态转换参数对比表
| 转换路径 | 触发条件 | 关键参数 | 典型值 |
|---|---|---|---|
| Closed → Open | 失败率 ≥ 阈值 & 请求数 ≥ 最小样本量 | errorThresholdPercentage, requestVolumeThreshold | 50%, 5 次 |
| Open → Half-Open | 休眠时间到期 | sleepWindowInMilliseconds | 30000 ms |
| Half-Open → Closed | 所有探测请求成功 | halfOpenMaxRequests | 3 次 |
| Half-Open → Open | 任意探测请求失败 | (无额外参数,复用原阈值) | — |
2.5 状态转换的工程实践要点
- 滑动窗口 vs 固定窗口:推荐使用滑动窗口统计失败率,避免固定窗口在边界处产生毛刺。
- 最小样本量保护:设置 requestVolumeThreshold 防止低流量时误触发熔断。
- 探测请求隔离:Half-Open 的探测请求应使用独立的线程池或超时配置,避免与正常请求竞争资源。
- 状态持久化:在分布式环境中,熔断器状态建议存储在本地内存(如 AtomicReference),而非外部存储,避免网络开销影响熔断时效。
面试高频题:“为什么需要 Half-Open 状态?”——因为 Open 状态无法感知下游是否恢复,Half-Open 通过小流量探测实现安全恢复,避免“惊群效应”或“雪崩恢复”。