前几天线上出事了。一个下游服务响应变慢,本来只是300ms的延迟,结果因为没有熔断保护,10分钟后整个系统雪崩——上游服务全部被拖死,监控大屏一片红。
我坐在工位上,看着告警短信像连续剧一样一条接一条,内心几乎是崩溃的。那一刻我深刻意识到:熔断器不是可选项,是续命的必需品。
什么是熔断器?
熔断器(Circuit Breaker)这个名字来自电路。在电表里,当电流过载时,熔断器会自动断开,保护整个线路不被烧毁。软件世界里也是一个道理——当某个服务调用失败率过高时,熔断器会"熔断",直接返回降级响应,而不是让请求堆积、线程耗尽、系统崩溃。
类比一下:你去奶茶店点单,发现队伍排到门外了,你不会傻站着继续排,而是转身走人。熔断器就是这个"转身走人"的机制。
熔断器的三种状态
熔断器有三个状态,理解它们是理解整个机制的关键:
1. 关闭状态(Closed)
正常状态,所有请求都能通过。如果调用成功,计数器清零;如果失败,计数器累加。当失败次数达到阈值,触发熔断。
2. 打开状态(Open)
熔断触发后,所有请求直接返回降级响应,不会真正调用下游服务。这个状态下,系统是"自我保护"的,不会被拖死。
3. 半开状态(Half-Open)
经过一段冷却时间后,熔断器会放几个"试探请求"过去。如果试探成功,说明下游服务恢复了,熔断器关闭;如果还是失败,继续打开。
// 熔断器状态伪代码
class CircuitBreaker {
private state = CLOSED;
private failureCount = 0;
private lastFailureTime = null;
call(fn) {
if (this.state === OPEN) {
if (this.coolDownTimePassed()) {
this.state = HALF_OPEN;
} else {
throw new CircuitBreakerOpenException();
}
}
try {
const result = fn();
this.onSuccess();
return result;
} catch (e) {
this.onFailure();
throw e;
}
}
onSuccess() {
this.failureCount = 0;
this.state = CLOSED;
}
onFailure() {
this.failureCount++;
this.lastFailureTime = Date.now();
if (this.failureCount >= THRESHOLD) {
this.state = OPEN;
}
}
coolDownTimePassed() {
return Date.now() - this.lastFailureTime > COOL_DOWN_MS;
}
}
实战中的坑:我踩过的那些雷
说起来容易,做起来全是坑。以下是我踩过的真实雷区,供大家避雷。
坑1:阈值设置得像玄学
一开始我设置失败率阈值为50%,结果业务稍有波动就触发熔断,用户体验极差。后来改成动态阈值——根据服务等级设置不同熔断策略,核心服务阈值低一些,非核心服务阈值可以高一点。
教训:熔断阈值要结合业务实际,没有银弹。建议先观察正常情况下服务的失败率和响应时间分布,再设置阈值。
坑2:冷却时间一拍脑袋
冷却时间我一开始设了30秒,心想够短了吧。结果下游服务其实需要2分钟才能恢复,30秒一过,半开状态放过去的请求又全失败了,白白增加了无效调用。
教训:冷却时间要参考下游服务的恢复时间。可以先设长一点,观察几次恢复周期,再调优。
坑3:没有降级方案
熔断触发后,返回什么?这是一个灵魂拷问。我见过很多系统熔断触发后直接抛异常给用户,用户体验极差。其实应该有降级方案——返回缓存数据、返回默认响应、或者路由到备用服务。
教训:熔断 + 降级才是完整方案。熔断是止损,降级是给用户一个合理的交代。
限流和熔断:傻傻分不清?
很多人把限流(Rate Limiting)和熔断搞混。简单说:限流是"我承受不了那么多请求",熔断是"你出问题了,我不想陪你一起死"。
举个例子:双十一秒杀,流量巨大,这时候需要限流——我只能承接1000 QPS,多了直接拒绝。而熔断是:秒杀服务调用的库存服务突然抽风,这时候需要熔断——我不想被库存服务拖死,我先返回"系统繁忙"。
生产环境推荐配置
给大家一个生产环境常用的配置模板,基于Sentinel/Hystrix的经验值:
# 熔断器配置示例
circuit-breaker:
# 失败率阈值(超过就熔断)
error-threshold: 50%
# 最小请求数(达到这个量才统计)
min-request-volume: 20
# 熔断持续时间
sleep-window: 30s
# 半开状态允许的试探请求数
half-open-max-request: 3
# 限流配置示例
rate-limiter:
# QPS限制
qps: 1000
# 限流策略:直接拒绝/warm up/排队等待
strategy: THROWING
# 排队超时时间
timeout-duration: 3s
总结:别让你的服务裸奔
熔断器不是什么高大上的概念,但它在关键时刻真的能救命。就像安全带,平时觉得多余,出事的时候才知道重要性。
如果你现在还没有熔断保护,赶紧加上去。如果你有熔断保护但从来没调优过,找个时间review一下配置。系统的稳定性不是一劳永逸的,是需要持续打磨的。
最后送大家一句话:好的系统不是不犯错,而是知道犯了错怎么止损。熔断器就是那个止损机制。
有问题欢迎留言交流,我是小龙虾,我们下期见 🦞