什么是熔断?
结论:熔断(Circuit Breaker)是当下游依赖的错误率或慢调用比例超过阈值时,主动切断对该依赖的调用,快速失败或走降级逻辑,避免调用方线程被慢请求耗尽、故障沿链路扩散。它有三个状态:关闭(CLOSED)、打开(OPEN)、半开(HALF_OPEN)。
一、三态状态机
错误率或慢调用比例超阈值
┌────────┐ ──────────────────────► ┌────────┐
│ CLOSED │ │ OPEN │
│ 正常放行│ ◄────────────────────── │ 直接失败│
└────────┘ 半开探测成功 └───┬────┘
▲ │ 等待窗口结束
│ ┌───────────┐ │
└───────────│ HALF_OPEN │ ◄────────┘
探测成功 │ 放行少量 │
└─────┬─────┘
│ 探测失败
▼
回到 OPEN,窗口可翻倍
- CLOSED:正常调用,同时用滑动窗口统计成功率与慢调用比例。
- OPEN:直接拒绝,不再发起真实调用,通常配合降级(Fallback)返回兜底值。
- HALF_OPEN:窗口结束后放行少量探测请求,成功则恢复,失败则继续熔断。
二、触发条件
| 指标 | 含义 | 典型阈值 |
|---|---|---|
| 慢调用比例 | RT 超过阈值的请求占比 | 50%,RT 阈值 800 ms |
| 异常比例 | 异常请求占比 | 50% |
| 异常数 | 窗口内异常绝对数量 | 10 次 / 10 秒 |
| 最小请求数 | 统计样本下限 | 20 次,避免样本太少误判 |
滑动窗口(Sliding Window)通常按秒分桶,统计最近 N 秒;窗口越大越平滑,但也越迟钝。
三、配置:Sentinel 与 Resilience4j
# Sentinel 熔断规则
[
{
"resource": "queryOrderFromPay",
"grade": 1, # 0=慢调用比例 1=异常比例 2=异常数
"count": 0.5,
"slowRatioThreshold": 0.5,
"timeWindow": 10,
"minRequestAmount": 20,
"statIntervalMs": 10000
}
]
# Resilience4j
resilience4j:
circuitbreaker:
instances:
payClient:
sliding-window-type: COUNT_BASED
sliding-window-size: 50
failure-rate-threshold: 50
slow-call-duration-threshold: 800ms
slow-call-rate-threshold: 60
wait-duration-in-open-state: 10s
permitted-number-of-calls-in-half-open-state: 3
四、熔断必须配降级
@SentinelResource(value = "queryPayStatus", fallback = "payStatusFallback")
public PayStatus queryPayStatus(String orderNo) {
return payClient.query(orderNo);
}
// 熔断或异常时走这里:返回「处理中」,让前端轮询,而不是直接报错
public PayStatus payStatusFallback(String orderNo, Throwable t) {
log.warn("支付状态查询降级 orderNo={} cause={}", orderNo, t.toString());
return PayStatus.PROCESSING;
}
没有 fallback 的熔断,只是把「慢失败」变成「快失败」,用户体验未必更好。
五、常见追问
Q1:熔断和限流有什么区别? 限流控制进入系统的流量,按 QPS 或并发数拒绝;熔断控制对某个依赖的调用,依据错误率与 RT,属于对故障的被动响应。
Q2:半开状态为什么只放少量请求? 探测期若放全量,故障未恢复会立刻再次打崩下游;只放 1 到 3 个请求,成本可控,又能验证依赖是否恢复。
Q3:熔断阈值怎么定? 基于 SLO 反推:允许的失败率是多少、下游恢复需要多久。阈值太低会误熔断,正常抖动也断开;太高则失去保护意义。通常从 50% 与 10 秒窗口起步,再按压测调整。
Q4:写操作被熔断会不会丢数据? 会。写类操作必须靠重试、补偿或最终一致机制处理,不能简单丢弃;读类操作才适合直接返回兜底值。
小结
- 熔断是依赖故障时的快速失败开关,三态切换由错误率与慢调用比例驱动。
- 熔断必须配降级,否则只是把超时变成立即报错。
- 阈值从 SLO 反推,再用压测校准,避免误熔断。