Linux 性能排查实战:机器变慢了,按这个顺序查
最危险的应对是「凭感觉动手」:先重启、先扩容、盯着 top 最高的进程下结论。这篇给出一套稳定顺序——先全局、再进程、后内部,四把刀(CPU、内存、磁盘、网络)各自怎么下。
一、第一步永远是全局:负载与四类资源
服务器变慢时,性能排查有一套稳定的顺序:先看全局(负载与四类资源),再定位进程,最后钻进进程内部。每一步都用数据说话,不猜。先跑三条命令,三十秒建立全局判断:
uptime # 负载(load average)与运行时长
free -m # 内存总量、已用、可用、缓存
iostat -x 1 3 # 磁盘:每秒看一次,共三次
第一个关键认知:load 高不等于 CPU 忙。load 统计的是「可运行 + 不可中断」的进程数——大量进程卡在磁盘 IO(D 状态)时,CPU 可能非常空闲,但 load 照样飙升。所以看到 load 高,先别急着怪 CPU。
| 指标 | 含义 | 高了说明什么 |
|---|---|---|
| us | 用户态 CPU | 应用在算东西(正常) |
| sy | 内核态 CPU | 系统调用密集(锁、IO、网络) |
| wa | IO 等待 | 磁盘瓶颈的强信号 |
| id | 空闲 | 越低越紧张 |
性能排查的顺序比技巧更重要:先全局、再进程、后内部;每一步都看数据、说话、再动手。
二、四把刀:一张症状对照表
| 症状 | 第一命令 | 关键指标 |
|---|---|---|
| CPU 飙高 | top -H -p PID |
哪根线程在烧 CPU |
| 内存异常 | free -m / dmesg -T | grep oom |
available 与 OOM 记录 |
| 磁盘慢 | iostat -x 1 / iotop -o |
%util、await、读写队列 |
| 网络异常 | ss -s / nstat |
连接数、重传、TIME_WAIT |
CPU:找到那根线程
top -H -p 12345 # 按线程展示,找到耗 CPU 的 TID
pidstat -u -p 12345 1 # 每秒采样,看趋势
perf top -p 12345 # 直接看热点函数(需权限)
三步走:进程 → 线程 → 函数。Java 场景可以把 TID 转成十六进制去抓线程栈,定位到具体代码。
内存:看清是缓存还是泄漏
free -m # 关注 available,而非 free
ps -eo pid,rss,cmd --sort=-rss | head # 看谁占得最多
dmesg -T | grep -i oom # 有没有被 OOM Killer 杀过
两个高频误判:Linux 会拿空闲内存做文件缓存,free 变小是正常现象——要看 available 这一列;数 GB 的 page cache 不是内存泄漏——它随时可回收。
磁盘:等出来的慢
iostat -x 1 # %util 接近 100%、await 明显升高 → 磁盘饱和
iotop -o # 只显示真正在读写磁盘的进程
df -h # 分区是否写满
lsof +L1 # 列出被删除却仍占空间的文件句柄
磁盘问题的经典三连:%util 高、await 高、wa 高。若机器 load 高但 CPU 空闲,八成就是这里。顺带一个高频事故:磁盘显示已满但找不到大文件——多半是「被删除但仍被进程持有」的文件,用 lsof +L1 找出来。
网络:连接与重传
ss -s # 各状态连接数汇总(TIME_WAIT 暴涨要留意)
ss -tnp # 看具体连接与所属进程
nstat -az | grep -i retrans # 重传计数(增长快 = 网络质量差)
如果机器指标都正常,但接口就是慢,别死磕本机——把下一跳也纳入排查:DNS 解析、连接池、下游 RTT。
三、四个典型场景的排法
- load 飙高但 CPU 空闲:九成是 IO 等待或不可中断进程——先找 D 状态进程,再顺着查它在等哪块盘
- 内存持续上涨:先看是 cache 还是进程 RSS;只有 cache 涨 → 正常,某进程 RSS 持续上行 → 查对象分配与连接泄漏
- 本机正常但接口慢:跳出本机——网络 RTT、DNS、下游依赖、连接池耗尽,逐个排除
- 磁盘满但找不到大文件:df 与 du 对不上时,用 lsof +L1 找被删除仍被持有的句柄,重启对应进程即释放
四、进阶:什么时候上火焰图
当 CPU 高但看不出明显热点(top 里没有突出进程、perf top 也散),就该上火焰图:
perf record -F 99 -p 12345 -g -- sleep 30
perf script > out.perf
# 用 FlameGraph 工具链生成 SVG,横向宽度 = CPU 时间占比
火焰图的读法:找最宽的「塔」——那是耗时最多、最值得优化的调用路径。它把「哪个函数慢」的问题,从猜测变成了可视化。
五、五个常见坑
- 只看 free 不看 available:把文件缓存当成内存泄漏,白白紧张半天
- 拿 top 的高 CPU 排序直接下结论:短命进程可能只是瞬间冒头,要用 pidstat 看趋势
- 忽略 wa 与 D 状态进程:load 高的真凶往往是 IO,不是 CPU
- 在容器里拿宿主机的指标说事:容器内 top 看到的是宿主机视角,cgroup 限额要看 /sys/fs/cgroup 对应文件或容器监控
- 没有基线:不知道「平时是多少」,就无法判断「现在是不是慢」——基线要提前采集
六、把排查变成流程
- 三板斧顺序:全局(uptime / top / free / iostat)→ 定位进程(pidstat / iotop)→ 进程内部(perf / strace / 堆栈)
- 优先只读:生产上先用只读命令;strace、perf 有开销,评估后再上
- 每次留记录:时间、现象、命令、数据、结论——三次之后你就有了团队的排查手册
- 基线先行:新服务上线时采集基线(正常时的 load、延迟、连接数),出问题才有对照
速查卡
| 症状 | 命令 | 看什么 |
|---|---|---|
| 变慢了,先看全局 | uptime / top / free -m | load 趋势、wa、available |
| CPU 飙高 | top -H -p PID / pidstat / perf top | 线程与热点函数 |
| 内存疑问 | free -m / dmesg oom / ps --sort=-rss | available、OOM、RSS 排行 |
| 磁盘慢 | iostat -x 1 / iotop -o | %util、await |
| 磁盘满但找不到文件 | lsof +L1 | 被删除仍持有的句柄 |
| 网络异常 | ss -s / ss -tnp / nstat | 连接数、重传 |
| CPU 高无热点 | perf record -g + 火焰图 | 最宽的调用塔 |
写在最后
性能排查的顺序比技巧更重要:先全局、再进程、后内部;每一步都看数据、说话、再动手。养成这个习惯,绝大多数「玄学变慢」都会在一次十分钟的排查里现出原形。
评论(0)