先看现象。网关用 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 秒内打开。
容易忽略的是,把超时吞成空值是最容易踩的坑,熔断看的应该是真实耗时和错误,不是业务层包装过后的返回值。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
