先看现象。网关用 resilience4j 的失败率熔断,阈值 50%,但上游超时是被业务层包成 200 的空结果,失败率一直是 0,下游连接池被打满后整站雪崩。

排查方向其实有限,先把可能性排一排。熔断只统计抛出的异常,超时被业务层吞成空响应。另一种情况是慢调用比例没有纳入熔断指标。

不容易想到的是,熔断粒度过粗,一个下游故障把全部接口一起断掉。

还有一种情况,半开探测只发一个请求,恢复判断过于乐观。

上来先统计各接口超时占比与耗时分布

python -c "import json;d=json.load(open('lat.json'));print(len(d))"

接着把慢调用比例加进熔断条件

python -c "print({'slow_ratio':0.3,'slow_ms':2000,'window':20})"

随后按下游维度拆分熔断器

python -c "print('breaker=per_downstream')"

压满一个下游验证隔离是否生效

python loadtest.py --target db --qps 200 --duration 60

改完先别撤,确认这几项。下游被打满时只有相关接口快速失败,其他接口 P99 保持 300 毫秒内,慢调用比例超过 30% 后熔断器在 5 秒内打开。

容易忽略的是,把超时吞成空值是最容易踩的坑,熔断看的应该是真实耗时和错误,不是业务层包装过后的返回值。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189