3. 半开状态核心原理:设计目的、有限请求与下游探测
半开状态(Half-Open)是熔断器从“开”到“关”的过渡状态,也是熔断器能否正确恢复的关键。如果熔断器在断开后直接切回关闭,可能立即被再次击穿;如果永远不尝试恢复,则服务永久降级。半开状态通过有限试探机制,在安全性与可用性之间取得平衡。
3.1 半开状态的设计目的
半开状态并非简单的“中间态”,它承载三个核心设计目标:
| 设计目标 | 说明 | 不采用半开的后果 |
|---|---|---|
| 防止雪崩回弹 | 下游刚恢复时能力脆弱,全量流量涌入可能再次压垮 | 熔断器反复开闭,系统震荡 |
| 快速自愈验证 | 用最小代价探测下游是否已恢复正常 | 人工介入恢复,MTTR 大幅增加 |
| 平滑过渡 | 从完全拒绝到完全放行之间提供缓冲 | 流量陡增导致下游瞬时过载 |
核心原则:半开状态的设计哲学是“试探而非信任”——在确认下游健康之前,只允许极小比例的请求通过,其余请求仍被快速失败。
3.2 允许有限请求通过
半开状态下,熔断器不会放行所有请求,而是按照试探窗口策略控制流量。常见的控制方式包括:
- 固定数量限制:每 N 秒只允许通过 1 个或少量请求(如 1 req / 5s)。
- 比例限制:允许通过正常流量的 1%~5%,其余直接返回 fallback。
- 自适应限制:根据上次试探的响应时间动态调整试探频率。
试探请求的选择通常遵循以下规则:
- 优先选择幂等请求(如 GET、HEAD),避免试探写操作造成数据不一致。
- 超时时间缩短:试探请求的超时设为正常超时的 1/2 或 1/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 半开状态状态机与决策流程
下图展示了半开状态在熔断器状态机中的位置,以及从半开到关闭/打开的完整决策路径:
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 可以在故障发生时快速定位熔断器是否处于“试探阶段”,并判断下游的真实恢复程度,从而避免误判或延迟恢复。