2. 熔断器模式(Circuit Breaker)原理
熔断器模式是分布式系统中防止级联故障的关键防护手段。其核心思想借鉴了电路中的熔断器:当系统检测到连续故障达到阈值时,主动切断对下游服务的调用,避免资源耗尽和故障扩散,并在适当时间后尝试恢复。
2.1 熔断器的三种核心状态
熔断器在运行过程中维护一个有限状态机,包含三种状态:Closed(关闭)、Open(打开) 和 Half-Open(半开)。三种状态的定义与行为如下表所示:
| 状态 | 含义 | 对请求的处理 | 计数器/计时器行为 |
|---|---|---|---|
| Closed | 熔断器关闭,系统正常运行 | 请求正常通过,调用下游服务 | 累计失败次数;失败率达到阈值时触发状态转换 |
| Open | 熔断器打开,系统进入降级保护 | 请求直接返回降级响应(如 fallback),不调用下游 | 启动超时计时器;计时器到期后自动进入 Half-Open |
| Half-Open | 熔断器半开,试探下游是否恢复 | 允许少量探测请求通过;其余请求仍走降级 | 根据探测请求的成功/失败结果决定下一步状态 |
2.2 状态转换机制
熔断器的状态转换由失败计数器和超时计时器共同驱动。下图展示了三种状态之间的完整转换路径:
状态转换的详细触发条件如下:
- Closed → Open:在滑动时间窗口内(如 10 秒),失败请求数达到预设阈值(如 5 次),或失败率超过百分比阈值(如 50%)。
- Open → Half-Open:熔断器在 Open 状态停留时间达到超时恢复时间(如 30 秒),计时器到期后自动转换。
- Half-Open → Closed:允许通过的探测请求全部成功,且成功次数达到预设的探测阈值(如 3 次),认为下游已恢复。
- Half-Open → Open:探测请求中任意一次失败,立即认为下游仍未恢复,重新回到 Open 状态并重置超时计时器。
2.3 熔断阈值与超时恢复策略
熔断器的行为由两个核心参数控制:熔断阈值和超时恢复时间。合理的参数配置是熔断器有效工作的前提。
2.3.1 熔断阈值
熔断阈值决定了从 Closed 状态切换到 Open 状态的触发条件。常见的阈值策略包括:
| 阈值类型 | 说明 | 典型配置 | 适用场景 |
|---|---|---|---|
| 计数阈值 | 在滑动窗口内累计失败次数达到指定值 | 5 次 / 10 秒 | 低流量服务,避免少量失败即熔断 |
| 比例阈值 | 在滑动窗口内失败请求占比达到指定百分比 | 50% / 10 秒 | 高流量服务,适应流量波动 |
| 混合阈值 | 同时满足计数和比例条件才触发熔断 | 失败次数 ≥ 5 且 失败率 ≥ 50% | 需要双重保障的关键业务 |
实践建议:对于核心支付链路,建议使用混合阈值(如 10 秒内失败 10 次且失败率 ≥ 30%),避免因单次突发流量导致误熔断;对于非核心日志上报服务,可使用计数阈值(如 5 次 / 30 秒)快速熔断,保护主链路资源。
2.3.2 超时恢复策略
超时恢复策略控制熔断器在 Open 状态停留的时间,以及进入 Half-Open 后的探测行为。常见的策略包括:
- 固定超时:熔断后等待固定时间(如 30 秒)后进入 Half-Open。实现简单,但无法适应故障恢复速度的变化。
- 指数退避:每次熔断的超时时间按指数增长(如 10s → 20s → 40s → 80s),避免频繁探测加重下游压力。
- 自适应超时:根据下游服务的响应时间或健康检查结果动态调整超时时间,需要额外的监控数据支撑。
进入 Half-Open 状态后,探测请求的数量和成功条件也需要明确:
| 参数 | 说明 | 推荐值 |
|---|---|---|
| 探测请求数 | Half-Open 状态下允许通过的请求数量 | 1 ~ 3 个 |
| 成功阈值 | 探测请求连续成功次数达到该值后关闭熔断器 | 与探测请求数一致 |
| 探测超时 | 单个探测请求的最大等待时间 | 与下游服务超时一致或略短 |
2.4 状态转换的代码示例
以下是一个简化的熔断器状态机实现,展示了核心的状态转换逻辑:
public class CircuitBreaker {
private State state = State.CLOSED;
private int failureCount = 0;
private final int failureThreshold = 5;
private final long timeoutMs = 30_000;
private long lastFailureTime = 0;
private int halfOpenSuccessCount = 0;
private final int halfOpenMaxSuccess = 3;
public synchronized boolean allowRequest() {
switch (state) {
case CLOSED:
return true;
case OPEN:
if (System.currentTimeMillis() - lastFailureTime > timeoutMs) {
state = State.HALF_OPEN;
halfOpenSuccessCount = 0;
return true;
}
return false;
case HALF_OPEN:
return true;
default:
return false;
}
}
public synchronized void recordSuccess() {
if (state == State.HALF_OPEN) {
halfOpenSuccessCount++;
if (halfOpenSuccessCount >= halfOpenMaxSuccess) {
state = State.CLOSED;
failureCount = 0;
}
} else if (state == State.CLOSED) {
failureCount = 0;
}
}
public synchronized void recordFailure() {
if (state == State.HALF_OPEN) {
state = State.OPEN;
lastFailureTime = System.currentTimeMillis();
} else if (state == State.CLOSED) {
failureCount++;
if (failureCount >= failureThreshold) {
state = State.OPEN;
lastFailureTime = System.currentTimeMillis();
}
}
}
private enum State { CLOSED, OPEN, HALF_OPEN }
}
注意:生产环境中不建议自行实现熔断器,应优先使用成熟的框架(如 Resilience4j、Hystrix、Sentinel)。上述代码仅用于演示状态转换的核心逻辑,未处理并发安全、滑动窗口统计、线程池隔离等复杂场景。
2.5 熔断器模式的核心价值
熔断器模式通过有限状态机实现了对下游故障的快速隔离和自动恢复,其核心价值体现在:
- 防止级联故障:单个服务故障不会扩散到整个调用链路,避免雪崩效应。
- 快速失败:熔断后请求立即返回降级响应,不阻塞调用方线程,释放系统资源。
- 自动恢复:通过 Half-Open 状态定期探测下游健康状况,无需人工介入即可恢复服务。
- 资源保护:减少对故障下游的无效调用,降低网络 IO、连接池、线程池等资源的消耗。