API 性能排障面试实战 — 从 200ms 飙到 3 秒的排查思路
来源:波波 | 发布日期:2026-06-02
场景还原
订单查询接口 /order/detail 的 P99 耗时从 200ms 飙升到 3.2s:
- 正常表现: P99 ≈ 200ms,QPS ≈ 500
- 异常表现: P99 → 3.2s,持续 10 分钟后恢复至 800ms
- 监控表象: CPU 60%,内存正常,数据库 CPU 40%,无死锁日志
- 业务反馈: 用户端加载订单详情明显卡顿
第一直觉:不是全系统崩溃,也不是数据库整体过载,更像是某个依赖或特定参数引发的慢查询或阻塞。
系统化排查方法论
第一层:确认影响范围(定界)
通过监控查看 P99/P95/P50 变化曲线,判断是少量长尾还是整体漂移:
- 整体漂移 → 公共依赖出了问题(数据库、缓存、RPC 服务)
- 少量长尾 → 特定参数触发了慢查询或大 key
同时确认是否所有实例都慢(负载均衡 vs 单机问题),以及错误率是否上升。
第二层:调用链分析(APM 定位瓶颈)
在 APM 平台(SkyWalking、Pinpoint 等)查看该接口的 trace 调用链:
- MySQL 慢查询: 抓慢 SQL →
EXPLAIN→ 看锁等待 - Redis 慢命令:
SLOWLOG GET 10→ 检查 big key - 下游 RPC: 检查下游服务状态、网络延迟
- 业务代码: 看日志中是否有新增循环批量操作或异常兜底逻辑
第三层:数据库慢查询深入诊断
如果 90% 时间花在一条简单的 WHERE order_id = ? 上,可能的原因及排查方式:
| 可能原因 | 排查方法 | 解决方案 |
|---|---|---|
| 索引失效 | EXPLAIN 看 type 是否为 ALL/index |
检查隐式类型转换、函数操作、OR 条件 |
| 统计信息陈旧 | SHOW INDEX 看 Cardinality |
ANALYZE TABLE 更新统计信息 |
| 锁竞争 | SHOW ENGINE INNODB STATUS |
优化事务隔离级别,减少行锁范围 |
| 硬件/I/O 瓶颈 | iostat 看延迟,top 看 wa |
排查磁盘故障或换 SSD |
| Buffer pool 污染 | 大量冷数据涌入将热数据挤出 | 冷热分离或增大 buffer pool |
第四层:连接池/线程池排查
HikariCP 最大连接数=20,通过 Micrometer 监控 hikaricp_connections_pending(等待连接数)和 hikaricp_connection_timeout:
- pending > 0 持续 → 连接池不够用
jstack看是否大量线程处于TIMED_WAITING→ 等待连接池获取连接
第五层:GC 问题定位
Java 8 + CMS 场景下,三种快速定位方法:
jstat -gcutil <pid> 1000— 看 YGC/FGC/FGCT 频率和耗时jmap -histo:live <pid> \| head -20— 看存活对象分布- GC 日志 + GCViewer/GCEasy — 分析 Full GC 频率、STW 时间、晋升率
生产推荐挂载 Arthas,用 dashboard 实时看 GC 和内存。
常见 GC 问题:
- 内存泄漏: Old Gen 持续增长 →
jmap导出 heap dump,MAT 分析 - 频繁 Young GC: Eden 区太小 → 调整
-Xmn/-XX:SurvivorRatio - CMS 并发模式失败: Old Gen 增长过快 → 增大 CMS 触发阈值
第六层:Redis 慢命令排查
场景:HGETALL 读取 100 万字段的 Hash 导致 Redis 阻塞
预防:
- 禁止
KEYS,改用SCAN - 大 key 拆分,Hash 单 key 字段数 ≤ 1000
redis-cli --bigkeys定期扫描
发现:
CONFIG SET slowlog-log-slower-than 10000+SLOWLOG GET 10- APM 中对 Redis 调用做埋点
临时处理: 业务层改为 HMGET 只取必要字段,或用本地缓存(Caffeine)减少 Redis 压力。
完整排查脑图
收到告警 → 接口耗时飙升
├─ 1. 确定范围:P99/P95 曲线 → 整体漂移 or 长尾
├─ 2. 调用链:MySQL 慢查询 / Redis 慢命令 / RPC 延迟 / 业务代码耗时
├─ 3. 系统层:top/vmstat/iostat → jstat/jstack → GC 日志
├─ 4. 中间件:数据库连接数/慢查询/死锁,Redis 慢查询/内存,MQ 堆积
└─ 5. 变更关联:最近发布?配置变更?依赖升级?→ 回滚验证
优先恢复,再找根因。kill 慢查询、临时扩大连接数、dump 堆内存、回滚版本都是合理的第一反应。
面试回答模板
"第一,确定影响范围和特征——看 P99/P95 变化,判断少量长尾还是整体漂移。 第二,借助调用链定位瓶颈——APM 上看 trace,定位耗时在哪一层。 第三,排查资源池和 GC——jstack 看线程状态,jstat 看 GC 频率。 第四,检查变更和异常——最近的发布、配置变更、依赖升级,必要时回滚。 最后,优先恢复,再找根因。"
关联页面
| 页面 | 关联点 |
|---|---|
| fullstack-performance-troubleshooting | 全栈性能排障方法论全景 |
| online-troubleshooting-checklist | 线上四维速查命令清单 |
| server-performance-four-dimensions | 服务器四维排查法(Netflix 黄金 60 秒) |
| cpu-spike-troubleshooting-guide | CPU 飙高专项排查 |
| ops-interview-50-questions | 运维经典面试 50 题 |
| devops-interview-guide | DevOps 面试指南(云原生侧重) |