3. 半开状态核心原理:设计目的、有限请求与下游探测

半开状态(Half-Open)是熔断器从“开”到“关”的过渡状态,也是熔断器能否正确恢复的关键。如果熔断器在断开后直接切回关闭,可能立即被再次击穿;如果永远不尝试恢复,则服务永久降级。半开状态通过有限试探机制,在安全性与可用性之间取得平衡。

3.1 半开状态的设计目的

半开状态并非简单的“中间态”,它承载三个核心设计目标:

设计目标 说明 不采用半开的后果
防止雪崩回弹 下游刚恢复时能力脆弱,全量流量涌入可能再次压垮 熔断器反复开闭,系统震荡
快速自愈验证 用最小代价探测下游是否已恢复正常 人工介入恢复,MTTR 大幅增加
平滑过渡 从完全拒绝到完全放行之间提供缓冲 流量陡增导致下游瞬时过载
核心原则:半开状态的设计哲学是“试探而非信任”——在确认下游健康之前,只允许极小比例的请求通过,其余请求仍被快速失败。

3.2 允许有限请求通过

半开状态下,熔断器不会放行所有请求,而是按照试探窗口策略控制流量。常见的控制方式包括:

  • 固定数量限制:每 N 秒只允许通过 1 个或少量请求(如 1 req / 5s)。
  • 比例限制:允许通过正常流量的 1%~5%,其余直接返回 fallback。
  • 自适应限制:根据上次试探的响应时间动态调整试探频率。

试探请求的选择通常遵循以下规则:

  1. 优先选择幂等请求(如 GET、HEAD),避免试探写操作造成数据不一致。
  2. 超时时间缩短:试探请求的超时设为正常超时的 1/2 或 1/3,避免试探请求长时间挂起。
  3. 独立计数:试探请求的成功/失败计数与正常请求隔离,防止污染统计。
// 半开状态试探逻辑示例(伪代码)
if (state == HALF_OPEN) {
    if (probeCounter < maxProbes) {
        // 允许当前请求通过,并启动超时计时器
        probeCounter++;
        result = callDownstream(timeout = normalTimeout / 2);
        if (result.success) {
            probeSuccessCount++;
            if (probeSuccessCount >= successThreshold) {
                transitionTo(CLOSED);
            }
        } else {
            transitionTo(OPEN);
            resetProbeWindow();
        }
    } else {
        return fallback("circuit half-open, probe limit reached");
    }
}

3.3 探测下游恢复情况

半开状态的探测本质是一个小样本假设检验过程。熔断器通过试探请求的连续成功/失败模式,判断下游是否已脱离故障状态。

常见的探测判定策略:

策略名称 判定条件 适用场景
连续成功阈值 连续 N 个试探请求成功(如 3 次) 下游恢复稳定,无毛刺
滑动窗口成功率 最近 M 个试探请求中成功率 >= 80% 下游存在偶发超时,但整体可用
响应时间基线 试探请求的 P99 延迟低于正常基线 2 倍 下游性能降级但未完全宕机
常见陷阱:仅依赖单次成功就关闭半开状态。如果下游是间歇性故障(如 GC 暂停、网络抖动),单次成功可能恰好落在正常窗口,关闭后立即被大量请求再次击穿。建议至少连续 2~3 次成功再切换。

3.4 半开状态状态机与决策流程

下图展示了半开状态在熔断器状态机中的位置,以及从半开到关闭/打开的完整决策路径:

熔断器半开状态决策流程 熔断器半开状态决策流程 CLOSED(关闭) OPEN(断开) HALF_OPEN(半开) 失败率 > 阈值 超时窗口到期 连续成功 ≥ N 试探失败 半开状态关键参数 • maxProbes:单次半开窗口允许的最大试探请求数(通常 3~5) • successThreshold:从半开切回关闭所需的连续成功次数(通常 2~3) • probeTimeout:试探请求超时(通常为正常超时的 1/2)

3.5 半开状态下的故障排查要点

在实际生产环境中,半开状态相关的故障通常表现为以下模式:

  • 反复震荡:半开→关闭→立即又断开。原因:successThreshold 设置过低(如 1),或下游恢复不稳定。
  • 永远半开:试探请求始终无法达到成功阈值。原因:下游实际未恢复,或试探请求超时设置过短导致误判。
  • 半开窗口过大:maxProbes 设置过高,导致半开状态下涌入过多请求,下游再次被打垮。
SRE 最佳实践:在半开状态期间,建议同时记录试探请求的响应时间分布和错误类型(超时 vs 5xx vs 连接拒绝)。如果试探请求虽然成功但延迟显著增加,说明下游可能处于“亚健康”状态,此时应提高 successThreshold 或延长半开窗口。

3.6 半开状态与标准模板的映射

在标准故障排查模板中,半开状态对应以下检查项:

模板阶段 半开相关检查 典型指标
故障确认 熔断器当前状态是否为 HALF_OPEN state=HALF_OPEN
影响范围 半开窗口内通过的请求量 & 成功率 probe_count, probe_success_rate
根因定位 试探请求失败的具体原因(超时/拒绝/错误码) probe_error_type, probe_latency_p99
恢复验证 连续成功次数是否达到阈值 consecutive_successes

通过将半开状态的核心原理与标准模板结合,SRE 可以在故障发生时快速定位熔断器是否处于“试探阶段”,并判断下游的真实恢复程度,从而避免误判或延迟恢复。