接口响应慢·系统化排查手册
一、整体思路:先分层,再定位
接口慢 = 某一层出现阻塞/等待/低效
自上而下分层:
客户端 → 网关/nginx → 应用服务 → 数据库/缓存 → 外部依赖
排查原则:
- 先看整体,再看局部
- 先看监控,再看日志
- 先复现,再定位
- 先治标(限流/扩容),再治本(优化代码/SQL)
二、第一步:确认现象与范围(5分钟)
先搞清楚慢的特征,避免盲目排查:
-
是偶发还是必现?
- 必现:代码/索引/逻辑问题
- 偶发:GC、锁竞争、网络抖动、流量突增、外部依赖波动
-
是全部接口慢,还是单个接口慢?
- 全部慢:服务器、JVM、中间件、数据库整体压力大
- 单个慢:该接口自身逻辑问题
-
是刚启动慢,还是运行一段时间后慢?
- 刚启动慢:类加载、连接初始化、缓存未预热
- 运行后慢:内存泄漏、连接池耗尽、锁竞争、数据量变大
-
高峰期慢还是平峰慢?
- 高峰慢:并发、线程池、限流、队列、数据库压力
- 平峰也慢:SQL 无索引、死循环、串行调用过多
三、第二步:服务器基础指标排查(最外层)
登录服务器或看监控,优先看:
1. CPU
- CPU 使用率高:死循环、大量计算、频繁GC、正则回溯
- CPU 使用率低但接口慢:IO阻塞(DB/Redis/外部接口)、锁等待
2. 内存
- 内存持续上涨:内存泄漏(ThreadLocal、连接未关闭、集合只增不减)
- GC频繁/FullGC多:STW导致接口直接卡住
3. 负载(Load Average)
- load 高但CPU低:IO密集、锁等待、磁盘IO高
4. 磁盘IO & 网络IO
- 磁盘IO高:日志疯狂打印、大量文件读写
- 网络高/延迟高:内网问题、第三方调用、大数据包传输
四、第三步:应用服务内部排查(核心层)
1. 看接口耗时分布
- 监控:P50/P95/P99 耗时
- 日志:全局过滤器打印接口耗时
2. 定位具体方法耗时
工具:
- Arthas:trace、watch、profile
- SkyWalking/Pinpoint:全链路追踪
- 手动:StopWatch 分段计时
常见问题:
- 循环内查询数据库(N+1)
- 串行调用多个外部接口
- 大量数据在内存处理(全表查询后业务过滤)
- 锁等待严重(synchronized、分布式锁)
- 线程池耗尽,请求排队
3. JVM 问题
- YoungGC/FullGC 频繁
- 堆外内存泄漏
- 线程死锁、活锁
- 连接池(DB/Redis/HTTP)耗尽
4. 中间件配置
- Tomcat 线程池过小
- 连接池最大连接数不足
- 超时时间设置不合理(太短导致重试风暴,太长导致阻塞)
五、第四步:数据库 & 缓存排查(最常见瓶颈)
1. 数据库慢
- 开启慢查询日志
- explain 分析SQL
- 重点看:
- type=ALL 全表扫描
- using filesort / using temporary
- 大表 deep limit
- 大事务、长事务
- 锁等待(行锁、表锁)
- 连接数打满、死锁
2. 缓存问题
- 缓存击穿/穿透/雪崩
- 大Key、热Key
- Redis 慢命令:keys *、hgetall、smembers
- 连接池满、序列化耗时高
六、第五步:外部依赖排查
接口本身没问题,但等别人导致慢:
- 第三方HTTP接口超时
- 第三方支付/短信/风控接口不稳定
- MQ 生产/消费阻塞
- 分布式锁等待时间长
- 内网服务调用超时(Dubbo/gRPC)
七、第六步:网关 & 前端 & 网络
- Nginx 限流、重试、buffer 设置不合理
- DNS 解析慢
- 网络丢包、内外网延迟
- 前端大文件、资源加载慢
- 请求参数/返回体过大
八、系统化定位流程(可直接背诵)
- 先看监控,确定是CPU、内存、IO、GC哪类问题。
- 再看是单个接口慢 还是整体服务慢。
- 用链路追踪定位到具体方法/SQL/外部调用。
- 若是数据库问题:查慢SQL、执行计划、索引、锁。
- 若是应用问题:查循环、锁、串行调用、线程池。
- 若是外部问题:查第三方接口、超时、重试机制。
- 最后核对中间件配置:线程池、连接池、超时、限流。
- 优化后压测验证,观察监控恢复情况。
九、常见根因总结(高频面试点)
- SQL 无索引/索引失效
- 循环查库 N+1
- 大事务/长事务
- 锁竞争严重
- 外部同步调用过多
- GC 频繁或 FullGC
- 连接池耗尽
- 热Key/大Key
- 数据量暴涨未分页
- 代码死循环/复杂计算