接口突然变慢别急着看数据库,这篇复盘把排查路径讲透了
一次真实线上接口 RT 飙升的排查复盘:从慢 SQL、线程池堆积到下游超时,最后怎么定位根因
大家好,我是一名有 4 年工作经验的 Java 后端开发。
很多时候,面试官真正想听的不是你会不会背概念,而是你有没有真实排过线上问题。
这篇文章我就用一篇偏复盘风格的内容,带你完整走一遍“接口 RT 飙升”的线上排查路径。
🦅个人主页
🐼
文章目录
- 一次真实线上接口 RT 飙升的排查复盘:从慢 SQL、线程池堆积到下游超时,最后怎么定位根因
- 一、事故背景
- 二、第一步:先确认问题是持续的还是抖动型
- 三、第二步:先看调用链,不要上来就盯数据库
- 四、第三步:看线程池是不是被拖住了
- 五、第四步:慢 SQL 有没有参与放大
- 六、第五步:为什么问题会放大成主链路事故
- 七、最终治理怎么做
- 7.1 优惠券 SQL 优化
- 7.2 优惠券服务加超时和熔断
- 7.3 订单确认页对非核心依赖做降级
- 7.4 线程池隔离
- 7.5 限制前端高频刷新
- 八、这次复盘最值得记住的点
- 8.1 先看链路,再看局部
- 8.2 问题常常不是单点,而是放大链路
- 8.3 非核心依赖一定要可降级
- 8.4 监控一定要能串起来
- 九、面试中怎么讲这种复盘
- 十、总结
- 十一、结尾
一、事故背景
某次大促期间,订单确认页接口在高峰时段突然出现明显抖动:
- 平均 RT 从
80ms上升到1.2s - TP99 从
300ms飙到4s - 用户侧开始大量投诉页面卡顿
- 应用实例 CPU 没有完全打满,但线程池活跃线程数明显上升
这个时候最重要的不是猜,而是快速缩小问题范围。
二、第一步:先确认问题是持续的还是抖动型
先看监控时,我重点观察了这些指标:
- 订单确认页 RT
- 错误率
- 应用线程池活跃数
- Redis RT
- MySQL 慢查询数
- 下游优惠券服务 RT
观察下来有两个明显现象:
- RT 是周期性抖高,不是一直高
- 每次 RT 抖高时,优惠券服务调用耗时也明显升高
这说明问题可能不是单纯应用本身,而更像:
- 某个下游变慢
- 或者线程池 / 数据库链路被带慢
三、第二步:先看调用链,不要上来就盯数据库
很多人这时候第一反应是:
- 查慢 SQL
但真实排障更稳的方式通常是:
先看链路,再看局部。
因为接口 RT 飙升不一定就是 SQL 慢,也可能是:
- 下游 HTTP 慢
- Redis 热点
- 线程池排队
- Full GC
链路追踪里很快看出一个关键现象:
- 确认页接口有多个下游依赖
- 商品服务和库存服务基本正常
- 优惠券服务调用耗时明显偏高
这一步已经把范围收缩了很多。
四、第三步:看线程池是不是被拖住了
再看应用线程池监控,发现:
- 处理确认页的业务线程池活跃线程数接近上限
- 队列长度持续上升
- 部分请求开始排队
这说明问题已经不只是“某次调用变慢”,而是:
- 下游慢调用把线程池逐渐拖满
- 排队导致 RT 继续放大
这个时候如果不及时做隔离或熔断,故障很容易继续扩散。
五、第四步:慢 SQL 有没有参与放大
虽然主因已经更像是下游超时,但数据库层还是要确认。
查了慢日志后发现:
- 订单确认页本身核心 SQL 没有明显恶化
- 但优惠券服务里有一条查询用户可用优惠券的 SQL 在高峰期慢了很多
继续 Explain 后发现:
- 这条 SQL 过滤条件较多
- 深分页和排序一起走
- 扫描行数明显偏高
也就是说:
优惠券服务之所以慢,不只是服务抖了,而是内部慢 SQL 把自己拖慢了。
六、第五步:为什么问题会放大成主链路事故
这一步特别关键。
根因链路大概是这样的:
- 优惠券服务内部一条 SQL 在高峰期变慢
- 优惠券接口 RT 上升
- 订单确认页同步调用优惠券服务,被阻塞
- 确认页线程池开始堆积
- 更多请求排队,RT 继续放大
- 用户刷新重试,又带来更多请求
也就是说,真正的事故不是一个点,而是一条完整放大链路。
七、最终治理怎么做
最终治理不是只做一件事,而是多点一起补。
7.1 优惠券 SQL 优化
- 改索引
- 去掉不必要的深分页
- 补充覆盖索引
7.2 优惠券服务加超时和熔断
- 避免持续拖慢主链路
- 超时后快速 fallback
7.3 订单确认页对非核心依赖做降级
优惠券展示不是绝对核心,所以高峰期允许:
- 不返回最优优惠券
- 只返回基础价格信息
7.4 线程池隔离
不要让慢依赖把主线程池全部拖死。
7.5 限制前端高频刷新
用户高频刷新本身也会继续放大问题。
八、这次复盘最值得记住的点
8.1 先看链路,再看局部
不要一上来就盯某一个组件。
8.2 问题常常不是单点,而是放大链路
慢 SQL 只是起点,线程池、重试、同步依赖才是放大器。
8.3 非核心依赖一定要可降级
不然很容易把主链路拖死。
8.4 监控一定要能串起来
如果没有:
- RT
- 下游耗时
- 线程池
- SQL
这些联合视角,排障会慢很多。
九、面试中怎么讲这种复盘
如果面试官问:
你有没有排查过线上接口 RT 飙升的问题?
你可以这样答:
第一,我会先判断 RT 飙升是持续型还是抖动型,并结合错误率、线程池、数据库、Redis、下游依赖的监控一起看,先缩小范围,而不是上来就猜。
第二,如果系统有链路追踪,我会优先看调用链,快速判断是应用内部慢、数据库慢,还是某个下游依赖变慢,因为接口 RT 问题很多时候是链路放大,不是单点问题。
第三,我会重点关注线程池和下游超时,因为很多慢调用最后都会放大成线程堆积和请求排队。真正的根因链路通常是“某个依赖先慢 -> 上游同步阻塞 -> 线程池堆积 -> 整体 RT 飙升”。
第四,治理时我不会只盯着某一层,而是同时补根因和放大器,比如 SQL 优化、超时熔断、降级、线程池隔离和重试收敛一起做。
十、总结
线上接口 RT 飙升这类问题,真正难的不是看懂某一张图,而是把:
- 链路
- 下游
- 线程池
- SQL
- 重试
这些因素真正串起来。
如果只记一句结论,我觉得可以记住这句:
线上 RT 问题最怕拍脑袋猜,最稳的方式永远是“先看链路、再看放大器、最后做组合治理”。
十一、结尾
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注。
后面我会继续整理一些更偏实战的 Java 后端和线上排障文章。
