2. 熔断器三种状态详解:Closed、Open、Half-Open 的状态转换机制与触发条件

熔断器(Circuit Breaker)是分布式系统中防止级联故障的核心模式。其本质是一个有限状态机,通过三个关键状态——Closed(关闭)、Open(打开)、Half-Open(半开)——以及它们之间的转换规则,实现对下游依赖的保护与自动恢复。理解这三种状态及其触发条件是设计自愈剧本的基础。

2.1 状态总览与核心对比

下表从请求处理行为、健康判断依据和典型触发条件三个维度,对三种状态进行横向对比:

状态 请求处理行为 健康判断依据 典型触发条件
Closed(关闭) 正常转发请求到下游,实时统计失败率 滑动窗口内的失败率 < 阈值 系统初始化、故障恢复后重置
Open(打开) 直接拒绝请求(快速失败),不调用下游 失败率 ≥ 阈值,触发熔断 连续失败次数/失败率超过预设阈值
Half-Open(半开) 允许有限数量的探测请求通过 探测请求的成功/失败结果 Open 状态持续达到超时时间
设计要点: Closed 状态是系统的“正常态”,Open 是“保护态”,Half-Open 是“试探恢复态”。三个状态形成一个闭环,确保系统在故障时快速隔离,在恢复时平滑回归。

2.2 状态转换机制与触发条件详解

2.2.1 Closed → Open:熔断触发

当熔断器处于 Closed 状态时,所有请求正常通过,同时熔断器会使用滑动窗口(如固定时间窗口或滑动时间窗口)统计请求的成功/失败情况。当统计结果满足以下任一条件时,状态从 Closed 切换到 Open:

  • 失败率阈值触发: 在滑动窗口内(例如最近 10 秒),请求失败率超过预设阈值(例如 50%)。
  • 连续失败次数触发: 连续 N 个请求全部失败(例如连续 5 次超时或返回 5xx)。
  • 最小请求量保护: 滑动窗口内的总请求数必须达到最小样本量(例如 10 个请求),避免因少量请求的偶然失败而误触发熔断。
避坑指南: 不要仅依赖失败率阈值。在低流量场景下,少量失败可能导致失败率瞬间飙升,从而误触发熔断。务必配合“最小请求量”条件一起使用。

2.2.2 Open → Half-Open:恢复试探

进入 Open 状态后,熔断器会启动一个熔断超时计时器(也称为休眠窗口)。在超时时间内,所有请求直接返回降级响应(如抛出异常或返回缓存数据),不调用下游。当计时器到期时,状态自动切换到 Half-Open:

  • 触发条件: Open 状态的持续时间 ≥ 预设的熔断超时时间(例如 30 秒)。
  • 设计意图: 给下游服务一个“冷却期”,让其有机会从故障中恢复(如重启、流量积压被消化)。
  • 超时时间策略: 固定超时(简单但不够灵活) vs. 指数退避超时(每次熔断超时时间翻倍,防止频繁试探)。

2.2.3 Half-Open → Closed 或 Open:试探决策

Half-Open 是熔断器的“决策窗口”。在此状态下,熔断器会放行有限数量的探测请求(例如 3 个并发请求),并根据这些请求的结果决定下一步状态:

  • Half-Open → Closed(恢复成功):
    • 触发条件:所有探测请求全部成功(或成功率 ≥ 恢复阈值)。
    • 行为:重置失败计数器,关闭熔断器,恢复正常流量转发。
  • Half-Open → Open(恢复失败):
    • 触发条件:任意一个探测请求失败(或失败率超过阈值)。
    • 行为:立即重新打开熔断器,重置熔断超时计时器(通常使用指数退避策略增加下次等待时间)。
最佳实践: Half-Open 状态的探测请求数量应远小于正常流量,避免在试探阶段对下游造成过大压力。同时,建议对探测请求设置更短的超时时间,以快速获得结果。

2.3 状态转换流程图

下图展示了熔断器三种状态之间的完整转换路径,以及每个转换的触发条件:

熔断器三种状态转换图 Closed(关闭) 正常转发请求 Open(打开) 快速拒绝请求 Half-Open(半开) 有限探测请求 失败率 ≥ 阈值 或连续失败 N 次 熔断超时时间到期 (休眠窗口结束) 探测请求全部成功 → 恢复成功 探测请求失败 → 恢复失败 说明:Closed → Open 由失败率触发;Open → Half-Open 由超时触发;Half-Open 根据探测结果决定回到 Closed 或 Open。

2.4 状态转换的代码示例(伪代码)

以下伪代码展示了熔断器状态机的核心转换逻辑,重点体现触发条件的判断:

class CircuitBreaker {
    state = CLOSED
    failureCount = 0
    successCount = 0
    lastFailureTime = 0
    halfOpenProbeCount = 0

    // 配置参数
    failureThreshold = 5          // 连续失败次数阈值
    failureRateThreshold = 0.5    // 失败率阈值(50%)
    minRequestCount = 10          // 最小请求样本量
    timeout = 30000               // 熔断超时时间(毫秒)
    halfOpenMaxProbes = 3         // 半开状态最大探测请求数

    function call(request) {
        if (state == OPEN) {
            if (currentTime - lastFailureTime > timeout) {
                state = HALF_OPEN
                halfOpenProbeCount = 0
            } else {
                return fallbackResponse()  // 快速失败
            }
        }

        if (state == HALF_OPEN) {
            if (halfOpenProbeCount >= halfOpenMaxProbes) {
                return fallbackResponse()  // 探测请求已满,等待结果
            }
            halfOpenProbeCount++
        }

        // 转发请求到下游
        response = sendRequest(request)

        if (response.isSuccess()) {
            if (state == HALF_OPEN) {
                // 探测成功:重置计数器,关闭熔断器
                resetCounters()
                state = CLOSED
            }
            recordSuccess()
        } else {
            recordFailure()
            if (state == HALF_OPEN) {
                // 探测失败:立即重新打开熔断器
                state = OPEN
                lastFailureTime = currentTime
                timeout = min(timeout * 2, maxTimeout)  // 指数退避
            } else if (state == CLOSED) {
                // 检查是否满足熔断条件
                if (failureCount >= failureThreshold ||
                    (totalRequestCount >= minRequestCount &&
                     failureRate >= failureRateThreshold)) {
                    state = OPEN
                    lastFailureTime = currentTime
                }
            }
        }
    }
}

2.5 状态转换的关键设计参数

在实际的熔断器实现中,以下参数直接影响状态转换的灵敏度和系统的稳定性:

参数名称 所属状态转换 推荐初始值 调优建议
失败率阈值 Closed → Open 50% 对延迟敏感的服务可降低至 30%
连续失败次数 Closed → Open 5 次 根据下游并发度调整,避免误触发
最小请求样本量 Closed → Open 10 个 低流量服务可降低至 5 个
熔断超时时间 Open → Half-Open 30 秒 结合下游平均恢复时间(MTTR)设置
探测请求数量 Half-Open 决策 3 个 不超过正常并发量的 10%
指数退避倍数 Half-Open → Open 2 倍 最大超时时间建议不超过 300 秒
调优原则: 熔断器参数没有“万能值”。建议在混沌工程实验中,通过注入不同级别的故障(如延迟故障、异常故障),观察熔断器的状态转换行为,逐步调整参数至最优。