4、熔断器核心状态机详解:Closed、Open 与 Half-Open

熔断器的核心是一个三态状态机:Closed(关闭)、Open(打开) 和 Half-Open(半开)。这三个状态之间的转换逻辑直接决定了 API 熔断的灵敏度和恢复效率。本章将逐一拆解每个状态下的工作机制、关键参数与实现细节。

核心原则:熔断器在 Closed 状态下累积失败计数,达到阈值后跳转为 Open 状态直接拒绝请求,经过冷却时间后进入 Half-Open 状态发送试探请求,根据试探结果决定恢复为 Closed 或再次进入 Open。
熔断器三态状态机转换图 Closed 正常调用,计数累积 Open 快速失败,拒绝请求 Half-Open 试探性恢复 失败数 ≥ 阈值 冷却时间到 试探成功 → 重置计数 试探失败 状态转换条件说明 • Closed → Open:滑动窗口内失败请求数达到阈值(如 10 次/10 秒) • Open → Half-Open:经过冷却时间(如 30 秒)后自动进入 • Half-Open → Closed:试探请求成功 → 重置计数器,恢复正常 • Half-Open → Open:试探请求失败 → 重新进入 Open,重置冷却计时

4.1 Closed 状态:请求计数与阈值

Closed 是熔断器的初始状态,此时 API 网关正常转发所有请求。熔断器内部维护一个滑动窗口计数器,用于统计最近一个时间窗口内的请求成功/失败情况。

4.1.1 滑动窗口计数机制

滑动窗口将时间划分为多个小桶(bucket),每个桶记录该时间段内的请求结果。窗口随时间向前滑动,自动丢弃过期数据。

参数 典型值 说明
窗口大小 10 秒 统计最近 10 秒内的请求数据
桶数量 10 个 每个桶覆盖 1 秒,精度 1 秒
失败阈值 10 次 窗口内失败请求数达到此值触发熔断
最小请求数 20 次 窗口内总请求数低于此值时不触发熔断(防止低流量误判)
失败率阈值 50% 失败数 / 总请求数 ≥ 50% 时触发熔断(可选)
最佳实践:建议同时使用绝对失败数阈值和失败率阈值。在低流量场景下,绝对失败数阈值起主导作用;在高流量场景下,失败率阈值能更快响应异常。

4.1.2 计数与阈值判断逻辑

每次请求完成时,熔断器执行以下判断流程:

  1. 记录结果:将请求结果(成功/失败/超时)写入当前时间桶。
  2. 聚合统计:计算滑动窗口内的总请求数、失败请求数、失败率。
  3. 前置检查:若总请求数 < 最小请求数,跳过熔断判断。
  4. 阈值比较:若失败数 ≥ 失败阈值 或 失败率 ≥ 失败率阈值,触发状态转换至 Open。
  5. 重置桶:若未触发熔断,继续累积下一个桶的数据。
// 伪代码:Closed 状态下的请求计数与阈值判断
class ClosedState {
    slidingWindow: SlidingWindow
    failureThreshold: int = 10
    minRequestThreshold: int = 20
    failureRateThreshold: float = 0.5

    function onRequestComplete(result: RequestResult) {
        // 1. 记录结果到当前时间桶
        slidingWindow.record(result)

        // 2. 聚合统计
        totalRequests = slidingWindow.getTotalRequests()
        failureCount = slidingWindow.getFailureCount()
        failureRate = failureCount / totalRequests

        // 3. 前置检查:低流量保护
        if (totalRequests < minRequestThreshold) {
            return  // 不触发熔断
        }

        // 4. 阈值比较
        if (failureCount >= failureThreshold ||
            failureRate >= failureRateThreshold) {
            transitionTo(State.OPEN)
        }
    }
}

4.2 Open 状态:快速失败

当熔断器进入 Open 状态后,所有发往该服务的请求将立即被拒绝,不再进行实际调用。这是熔断器保护下游服务最直接的手段。

4.2.1 快速失败机制

  • 直接返回降级响应:网关拦截请求,返回预设的降级数据(如空列表、缓存数据、错误码 503)。
  • 零网络开销:不建立 TCP 连接,不发送 HTTP 请求,避免占用连接池和线程资源。
  • 冷却计时器:进入 Open 状态时启动冷却计时器,计时结束后自动转换至 Half-Open。

4.2.2 冷却时间配置

场景 推荐冷却时间 说明
瞬时故障(如网络抖动) 5 ~ 15 秒 快速恢复,减少对用户的影响
服务过载(如 CPU 打满) 30 ~ 60 秒 给服务足够的恢复时间
数据库故障 60 ~ 120 秒 数据库恢复通常需要更长时间
长时间熔断 指数退避(如 30s → 60s → 120s) 防止频繁试探加重服务负担
注意:冷却时间不宜过短(< 3 秒),否则可能导致熔断器在 Open 和 Half-Open 之间频繁震荡,反而增加系统开销。建议最小冷却时间设为 5 秒。

4.3 Half-Open 状态:试探性恢复

Half-Open 是熔断器的恢复探测状态。在此状态下,熔断器允许有限数量的试探请求通过,用于验证下游服务是否已恢复正常。

4.3.1 试探请求策略

  • 试探请求数:通常设置为 1 ~ 3 个并发请求,避免试探流量过大。
  • 成功判定:所有试探请求成功 → 转换至 Closed,重置计数器。
  • 失败判定:任意试探请求失败 → 立即回到 Open,重置冷却计时器。
  • 超时处理:试探请求超时视为失败,防止慢调用影响判断。

4.3.2 试探请求的隔离性

试探请求应使用独立的超时配置和独立的连接池,避免与正常请求混用导致资源竞争。

参数 正常请求 试探请求 说明
超时时间 5000 ms 2000 ms 试探请求超时更短,快速判定
最大并发 200 1 试探请求严格控制并发数
重试策略 允许重试 2 次 不允许重试 试探请求一次失败即判定失败
Half-Open 试探请求决策流程 进入 Half-Open 发送 1 个试探请求 试探成功 试探失败 转换至 Closed 回到 Open

4.4 状态转换参数配置清单

以下清单汇总了熔断器三个状态的核心配置参数,供 MRM 模型验证时参考:

状态 参数 推荐值范围 验证要点
Closed 滑动窗口大小 5 ~ 30 秒 窗口过小易误判,过大响应慢
失败阈值 5 ~ 20 次 根据服务正常失败率调整
最小请求数 10 ~ 50 次 低流量保护,防止冷启动误熔断
失败率阈值 40% ~ 60% 与失败阈值配合使用
Open 冷却时间 5 ~ 120 秒 根据故障类型动态调整
降级响应 缓存 / 默认值 / 错误码 降级数据必须可用且安全
Half-Open 试探请求数 1 ~ 3 个 试探并发过高可能压垮恢复中的服务
试探超时 1000 ~ 3000 ms 短于正常超时,快速判定
MRM 验证建议:在模型风险监控中,应定期检查熔断器的状态转换日志,重点关注 Closed → Open 的触发频率。如果触发频率过高(如每小时超过 5 次),说明阈值设置可能过于敏感,或下游服务存在持续性问题,需要调整参数或触发告警。