——从 Linux → JVM → 业务代码的完整排查流程(强收藏)
性能优化的第一步不是“优化”,而是 定位瓶颈。
很多程序员一遇到问题就想调 GC、加线程池、加 Redis、加机器——这其实是方向错误。
真正的性能高手,首先会做的是:
找到最关键的那个瓶颈点,而不是盲目调整。
本篇给你一套 “线上必用、面试必问、运维认可” 的性能排查流程。
🧭 一、性能瓶颈定位的总思路
性能问题一般分 5 大类:
CPU 问题
内存 / GC 问题
线程问题
IO / 网络问题
DB(MySQL / Redis)瓶颈为了定位这些问题,我们可以用 三层排查法:
第 1 层:Linux 层排查 → 系统资源是否异常?
第 2 层:JVM 层排查 → GC、线程、内存是否异常?
第 3 层:业务层排查 → SQL / Redis / 代码逻辑 / 架构瓶颈?掌握这三层,你能解决 90% 的线上问题。
🔥 二、第一层:Linux 层排查(快速判断方向)
当系统出现:
CPU 100%
RT 延迟升高
QPS 急剧下降
线程阻塞
服务卡顿
先不要看 JVM,先看系统层数据。
✔ 1. top —— CPU / Load 大盘情况
top -Hp <pid>重点关注:
(1) load average 是否异常
load > CPU 核数 × 1.5 → 暂时过载
load > CPU 核数 × 2 → 严重过载
(2) CPU 占比
us(用户态)太高 → Java 计算/循环
sy(内核态)太高 → IO 问题
si(软中断)太高 → 网络瓶颈
wa(IO wait)太高 → IO/磁盘阻塞
(3) 哪个线程 CPU 最高?
top -Hp <pid>找到线程号(TID)后,再转换成 16 进制:
printf "%x\n" <tid>之后我们可以用 jstack 找到具体 Java 线程(后面讲)。
✔ 2. vmstat —— 内存、上下文切换
vmstat 1 5重点看:
cs(context switch)上下文切换是否过高
超过 4000/s 基本不正常
si / so(swap in/out)是否发生 swap
r (运行队列)是否过长
CPU 上下文切换太多,往往是:
线程太多
锁竞争
频繁 GC
✔ 3. iostat —— IO 是否瓶颈
iostat -x 1重点看:
%util → IO 设备利用率
长期 90%以上 = IO 满了
await → IO 延迟
IO 问题往往是:
大量日志写入
MySQL 写压力
Redis AOF 写压力
大文件读写
✔ 4. netstat —— 网络层是否阻塞
netstat -natp | grep ESTABLISHED | wc -l如果连接数爆炸 = 连接池问题、网关问题、雪崩效应。
netstat -s查看网络丢包、重传等信息。
🔥 三、第二层:JVM 层排查(GC、内存、线程)
Linux 层确认方向后,就进入 JVM 层排查。
核心工具:
jstat
jmap
jstack
jcmd
Arthas
✔ 1. jstat —— 查看 GC 情况(必用)
jstat -gc <pid> 1000重点看:
常见问题:
Full GC 频繁 → 内存不足 / 大对象 / 元空间不足
Minor GC 太频繁 → 新生代太小 / 对象创建太多
✔ 2. jmap —— Dump 内存分析
jmap -dump:live,format=b,file=heap.hprof <pid>用 MAT 分析:
哪些对象占用内存最多
是否发生内存泄漏
ThreadLocal 泄漏
缓存未清理
大集合无边界增长
✔ 3. jstack —— 线程分析
jstack <pid> > stack.log结合 top 找出的 TID:
能看到哪些线程问题?
死锁(Java 自带检测)
等待锁(BLOCKED)
GC 线程异常
任务堆积
线程池任务执行缓慢(大量 RUNNABLE)
频繁上下文切换
✔ 4. Arthas —— 强烈推荐的排查神器
arthas-boot核心命令:
Arthas 的 trace 能精确查出哪个方法最浪费时间,堪称神器。
🔥 四、第三层:业务瓶颈定位(SQL/Redis/代码/架构)
当系统资源和 JVM 方向明确后,就要深入业务层。
✔ 1. 数据库瓶颈排查
慢查询日志(重点)
开启 slow log,捕获 >200ms 的 SQL。
常见问题:
没有索引
全表扫描
联表太多
函数操作字段
limit 大分页
高并发写入
80% 的性能问题都出在 SQL。
✔ 2. Redis 瓶颈排查
重点查:
热 Key
大 Key(hash/set > 5W item)
pipeline 未使用
LUA 脚本未优化
锁(SETNX)导致阻塞
Redis 连接池耗尽
可以用:
redis-cli --latency
monitor
slowlog get 10
✔ 3. 线程池排查
常见错误:
核心线程数太少(吞吐低)
最大线程太大(CPU 上下文切换)
队列太大(堆内存撑爆)
建议监控线程池:
ActiveCount
QueueSize
CompletedTaskCount
✔ 4. 代码逻辑瓶颈
常见问题:
使用 synchronized 锁大范围代码
复杂循环
N+1 查询
无限重试
异常频繁抛出(非常耗性能)
🌟 五、一套标准的瓶颈定位流程(实战可用)
下面这套流程足够你解决大多数线上问题:
📌 Step 1:top 判断资源方向
CPU 是否异常?
IO/Load 是否高?
哪个线程最耗 CPU?
📌 Step 2:jstack 定位最耗 CPU 的 Java 线程
死循环?锁等待?线程池阻塞?
📌 Step 3:jstat 看 GC
FullGC 是否频繁?
GC 耗时是否过高?
📌 Step 4:jmap dump 内存
找到大对象泄漏。
📌 Step 5:Arthas trace 查代码耗时
trace 某个 Controller 或 Service:
trace com.xxx.OrderService createOrder
直接看到哪段代码最慢!
📌 Step 6:数据库 / Redis 排查
慢 SQL、慢日志、大 Key、热 Key。
📌 Step 7:线程池 / 调用链监控
是否有任务堆积?
是否存在雪崩?
是否出现服务链路阻塞?
🎯 六、结语:定位是优化的前置条件
没有定位,所有优化都是凭感觉。
有了这篇文章的流程,你的排查能力会立刻提升一个等级。
下一章会正式进入 JVM 深水区:
默认评论
Halo系统提供的评论