最后更新:2026-10-28 · 基于第 1 次作答
结论:RT 飙高先切维再归因——按单接口/单机/全量三个维度切分故障范围,再用链路追踪(单接口)、GC+线程池(单机)、中间件+依赖(全量)三套独立证据链归因;关键判据是「Load 高 CPU 低 = IO/锁等待,不是计算瓶颈」。 关键词:先切维 · 单接口/单机/全量 · 链路追踪 · 线程 Dump · CPU 分解 · FullGC 基线 边界:适用于线上接口 RT 整体或部分飙高的被动排障;发布后首批高且自愈属冷启动,不在此排查链;伴随错误率升高需先看依赖熔断与降级状态。
核心考点定位:RT 飙高排查的核心方法论是「先切维再归因」。用实例、接口、时间三个维度把故障范围切成两半,差异维度直接指向根因;再对每个维度用独立证据链归因。难点在于区分「CPU 计算瓶颈」与「IO/锁等待」——二者对策完全相反,是排障题里最常见的方向性错误。
机制链(≥3 环):
SkyWalking 可直观看到耗时分布证据锚点:
SkyWalking:链路追踪定位慢 span,区分自身/Redis/MySQL/RPC 调用jstack:看线程状态分布——RUNNABLE/BLOCKED/WAITING 指向计算/锁/等 IOjstat -gcutil:看 FGC 次数与 FGCT 累计耗时,FullGC 基线趋势判泄漏pidstat -w:看 cswch/s(自愿切换=锁/IO)与 nvcswch/s(非自愿=时间片耗尽)%usr:用户态计算热点(死循环、序列化、正则回溯、CAS 自旋)%sys:内核态调用(频繁 syscall、锁竞争、上下文切换)%wa:等 IO(磁盘慢、网络等待)top -Hp:找高 CPU 线程 TID,转十六进制后 jstack 匹配栈帧async-profiler:采样式定位 CPU 热点,替代 jstack 快照HikariCP:connectionTimeout 反映连接池排队耗尽ThreadPoolExecutor:CallerRunsPolicy 背压,队列满时拖回调用方top 仅显示约 12.5%(整机口径)对比与权衡:
| 方案 | 正确性 | 吞吐/成本 | 失败模式 | 适用边界 |
|---|---|---|---|---|
| 先切维再归因 | 高(维度差异直接指根因) | 低(先看几个指标即可) | 切错维度会漏根因 | 所有 RT 异常通用 |
| 直接猜答案(先查慢 SQL) | 低(方向性错误常见) | 中(可能白查一轮) | CPU 高≠SQL 慢,锁等待被误判 | 仅现象单一明确时 |
| 一把抓线程 Dump | 中(能看阻塞与死锁) | 高(多实例采样成本大) | 快照无法证明热点 | 必须配合 CPU 分解 |
| 只盯平均值 | 低(掩盖长尾) | 低 | 恶化被快请求稀释 | 不作为判据 |
常见误区:
%usr 高有多种成因,需先分解再定位适用边界:本讲解适用于「线上接口 RT 整体或部分飙高」的被动排障;若为发布后首批高且 10-30 分钟自然回落,属冷启动(JIT/缓存/连接池/流量分配),不在此排查链;若伴随错误率升高或丢单,需先看依赖可用性、熔断降级与超时重试配置,而非直接进 GC/线程排查。
grep "waiting to lock" | sort | uniq -c),配 pidstat -w 看 cswch/s;JFR jdk.JavaMonitorBlocked 定位具体锁与代码行。%wa 高=磁盘/网络等待,cswch/s 高=锁/IO 自愿切换),不是计算瓶颈;对策是查磁盘/网络/锁,而不是加机器。%usr/%sys/%wa 分解,pidstat -w 区分自愿/非自愿切换。jstat -gcutil 多次采样,看每次 FGC 后老年代基线是否逐次抬高;抬高=内存泄漏(找 GC Roots 持有者),回到同基线=分配速率过高/堆太小。CallerRunsPolicy 背压。【结论】 RT 飙高排查的关键是先切维再归因:按单接口/单机/全量三个维度切分,再对每个维度用独立证据链归因;关键判据是 Load 高 CPU 低 = IO/锁等待而非计算瓶颈。
【三点】 第一,单接口 RT 高,用链路追踪(SkyWalking)看 span,定位慢 SQL 或三方调用;第二,单机所有接口 RT 高,先看监控是否 GC 异常(jstat -gcutil 看 FGC 次数与 FGCT),再抓 jstack 看线程状态(BLOCKED=锁竞争、RUNNABLE=计算、WAITING=等 IO),辅以 pidstat -w 看上下文切换;第三,全量接口 RT 高,查中间件(Redis 慢查询、DB 慢 SQL、MQ 堆积)与依赖超时,警惕超时重试放大。补充判据:Load 高 CPU 低=IO/锁等待;CPU 高先分 %usr/%sys/%wa。
【边界】 适用于被动排障;发布首批高且自愈属冷启动;伴随错误率升高需先看依赖熔断与降级,而非直接进 GC/线程排查。
题目:RT飙高问题排查过程
难度:medium
标签:practice/debug · os/cpu · os/load · network/debug
评分:⭐⭐⭐☆☆(3/5)
RT出现标高,先定范围,是某个接口出现标高,还是大批接口出现标高?还是某些机器的接口标高,其他机器接口不高,对应有不同的排查;单个接口标高,去检查调用链路,是否链路上出现问题,某个sql,或者某个三方应用,这种可以很直观的在skywalking等链路追踪工具中查看到;如果是某个机器上的接口都rt标高,那么检查下监控,看是否出现gc异常,有大量级的gc导致这台机器上的接口都出现超时,无法正常访问;如果是大批量接口出现rt飙高,那么检查下是否某个中间件出现问题,或者机器收到工具,有大量链接阻塞其他访问;查看指标可以看cpu使用率,检查数据库是否有慢SQL,检查redis是否出现无法正常使用,redis上是否有慢查询;
评分:⭐⭐⭐☆☆(3/5)
优点:先定范围再排查的分层思路(单接口/单机/全量)排查方法论正确;区分单接口链路/单机GC/全局中间件三类根因判断准;提到链路追踪工具 SkyWalking。
不足:没提 CPU/GC 的具体判据(Full GC 频率/STW 时长/GC 日志);没提线程 Dump 分析(jstack 看 BLOCKED/死锁/池耗尽);没提 Load 与 RT 的关联(Load 高但 CPU 不高→IO 等待/锁等待而非计算瓶颈);没提连接池耗尽(DB/Redis 连接池、Tomcat 线程池)、依赖超时(下游 RT 放大导致本服务线程被占满)。
补充:补①jstack 看线程状态(RUNNABLE/BLOCKED/WAITING)定位锁与池;②Full GC 判据(频率/GC 日志耗时/基线趋势);③Load 高 CPU 低=IO/锁等待;④线程池/连接池耗尽放大。
完整讲解见上方「完整讲解(权威版)」