Linux性能排查实战:从CPU负载到内存泄漏的定位指南 1. 整机体检最先敲的几个命令拿到一台新服务器或者感觉系统变卡的时候我最先做的不是去看监控面板而是直接开终端敲几个老命令。这些命令就像给机器量体温、测血压几十秒就能定位问题基本盘。核心关键词就三个内存、CPU、GPU显卡挨个排查其实顺序有讲究。先看整体负载再看具体进程最后才碰硬件细节。很多人习惯一上来就top这没错但我更推荐先跑一遍free -h和uptime原因很简单先用最便宜的命令确认“是不是真有问题”再决定要不要花精力深挖。uptime输出里的 load average 三个数字很有迷惑性。新手容易看到 16 就觉得完蛋了其实要结合 CPU 核数判断。比如一台 32 核机器load 16 说明还有一半余量如果是 4 核机器load 16 早就卡到鼠标都动不了了。这个知识点我在后面 CPU 部分会详细展开这里先记住一个原则load average 要和 CPU 核数对比着看单看绝对数值没有意义。free -h则是看内存的第一道入口它会告诉你物理内存总量、已用、可用和缓存占用。注意这里有个经典误区free命令里显示的 used 内存并没有把 buff/cache 算进去所以经常出现“used 才 8G但应用已经 OOM 了”的诡异情况。真正要注意的是 available 那一列这才是操作系统实际可分配给新进程的内存余量。如果 free 和 uptime 看下来一切正常比如 load 不高、available 内存充足那问题大概率不在整机层面这时候再往进程级别和硬件级别排查。反过来如果 available 内存快见底了或者 load 明显超出核数那就进入下一轮深挖。顺带推荐一个我自己装在每台机器上的工具htop它是 top 的增强版支持鼠标操作、树形进程显示和颜色区分。虽然生产环境不一定允许装额外软件但在自己运维的机器上装一个排查问题时视觉体验好很多进程的内存占用排序、CPU 占用排序一屏就能看懂。后面几个部分的内容我会默认你手头有 root 权限或者至少 sudo 权限因为有些命令需要读/proc或调用系统接口普通用户会有权限限制。2. CPU 排查从负载到单核到进程一层一层往下挖2.1 别只看 top 那一行load average 要这么解读关于 CPU 排查我最常被问到的就是“load average 多少算正常”。这个问题真没有标准答案但我可以给一个比较好用的估算思路load average 长期超过 CPU 逻辑核数的 70%就该警惕了超过 100%那基本可以断定 CPU 是瓶颈。怎么看逻辑核数最简单的是nproc输出一个数字。想看得更细就用lscpu里面有 Architecture、CPU(s)、Core(s) per socket、Thread(s) per core 这些信息。比如输出显示 CPU(s): 16Core(s) per socket: 8Thread(s) per core: 2说明这是一颗 8 核 16 线程的 CPU。load average 的三个数字分别代表过去 1 分钟、5 分钟、15 分钟的平均负载。我通常这样判断趋势如果 1 分钟明显大于 15 分钟说明负载正在快速上升系统刚刚开始变卡如果三个数字都很高而且差不多说明已经持续高负载一段时间了可能不是瞬时任务导致的。这里要区分“负载高”和“CPU 占用高”是两回事。负载高可能是有大量进程在等待 I/O磁盘、网络CPU 其实在摸鱼CPU 占用高才是真正在密集计算。所以遇到 load 高我会用top看一眼 %Cpu(s) 那行里的waI/O wait列如果 wa 也高那就不是 CPU 的锅得去查磁盘或网络。2.2 定位吃 CPU 的进程top/pidstat 组合拳确认 CPU 真的繁忙之后下一步就是找“元凶”。top进去默认按 CPU 使用率排序第一屏就能看到最吃 CPU 的几个进程。但 top 有个缺点它显示的 CPU 使用率是累计值有时候瞬时冲高的进程会被平均掉。所以我更喜欢用一段时间的采样来抓真凶。pidstat是好帮手比如采样 5 次、间隔 2 秒pidstat -u 2 5这会输出每个进程在这 10 秒内的 CPU 使用率变化。重点看最后几列的变化趋势如果某个进程持续 80% 以上基本就是它没跑了。找到 PID 之后用top -H -p PID查看这个进程内部的线程占用能进一步确认是哪个线程在忙这对 Java 应用尤其有用配合jstack能直接定位到代码行。还有一个我经常用的场景机器突然卡顿但top里的进程看起来都正常。这种时候我会怀疑是内核线程或者不可中断的进程在搞鬼。top里按Shift P按 CPU 排序再按Shift H切换线程视图如果看到[kworker]或者[ksoftirqd]这类中括号进程占用高那就要往内核模块、驱动或者硬件故障方向排查了。2.3 多核 CPU 分布不均怎么判断是不是绑核问题现在服务器基本都是多核多路架构还有一个值得关注的点CPU 使用率在所有核上的分布是否均匀。mpstat -P ALL 2能列出每个逻辑核的使用率。如果发现某些核长期 100%其他核长期空闲可能是进程绑核CPU affinity导致的。查看进程绑核情况可以用taskset -cp PID如果输出的 CPU 列表不是全部核说明确实绑了。解除绑核用taskset -cp 0-15 PID把可用核范围重新设置一下。但要注意生产环境不要随便动绑核设置有些应用比如 NFV 数据面、DPDK是故意绑核的乱解除可能引发更严重问题。再补一个判断 CPU 是否成为瓶颈的辅助手段vmstat 2。看us用户态和sy内核态两列。正常情况下 us 高说明应用在密集计算sy 高则需要关注系统调用是否频繁、是否有锁竞争。如果us很低但sy很高可能是频繁的系统调用导致的这时候排查方向就要转向应用代码了而不是盲目加 CPU 资源。3. 内存排查free 只是起点真正重要的是理解内存机制3.1 理解 free 输出total、used、buff/cache 和 available 的区别很多人看free -h只盯着 used 那一列以为 used 就是真实使用量这坑了我好久。内存方面我推荐大家先牢牢掌握 available 这个概念。Linux 内存管理的核心机制是“能用就用”内核会尽量把空闲内存用作 page cache文件缓存所以 used 高不代表内存紧张真正决定系统是否缺内存的是 available。free -h输出里buff/cache 包含两部分buffer 是块设备缓存cache 是文件系统页缓存。这俩在系统内存充裕时会尽量占满但在内存紧张时可以被内核自动回收。所以判断内存够不够不要看 used要看 available。比如下面这种情况total used free shared buff/cache available Mem: 31Gi 12Gi 3.0Gi 233Mi 16Gi 17Giused 才 12Gi好像很少但 available 是 17Gi意味着真正可用的内存还有 17Gi。哪怕 buff/cache 占了 16Gi压力来临时内核会先回收一部分缓存来满足进程需求。反过来如果 available 只有几百 Mi即使 used 看起来不高也说明内存是真的紧张了。那什么时候该关注 used观察内存泄漏的时候。一个进程的常驻内存RSS持续增长且不回落那就是泄漏的信号。用pidstat -r 2 5可以按进程观察内存变化比盯着整机 used 直观得多。3.2 进程内存占用视图top/ps/free 一个都不能少定位某个应用吃内存我常用一套组合拳。先用top按内存排序Shift M看看哪个进程 RSS 最大。再用ps aux --sort-rss按物理内存排序打印前几个进程命令输出里%MEM列能直接看到占系统总内存的百分比。这里有个细节要注意RSSResident Set Size是一个进程实际驻留在物理内存中的部分但它包含共享库所以所有进程 RSS 加起来会远大于系统总内存。更精确的指标是 PSSProportional Set Size按共享占比均摊了共享内存。smem命令能输出 PSS但默认没装需要手动安装。实际排查场景中我更关注的是单个进程的内存增长趋势而不是静态的 RSS 值。怎么观察连续采样几次pidstat -r 2 10如果 PID 的 RSS 只增不减那八成有内存泄漏。如果再配合cat /proc/PID/status看 VmRSS 和 VmSwap还能判断进程是否发生了 swap。VMSwap 非零说明内存不足时内核把该进程的某些页换到交换分区了这通常会伴随明显的性能下降。3.3 内存不够用的自救手段swap、OOM 和缓存回收机制内存真的不够用了Linux 内核有两个兜底机制分别是 swap 和 OOM killer。理解它们的行为对排查问题很重要。swap 就是把一部分磁盘空间当成内存用但性能差距是数量级的所以一旦系统开始大量 swap应用就会变得非常卡。查看 swap 使用情况用free -h的 Swap 行或者vmstat 2的 si/so 两列swap in/out。持续非零就要高度警惕。OOM killer 是内核在内存耗尽时的最后手段它按策略选一个进程直接杀掉。很多人在生产环境遇到的“莫名其妙进程不见了”其实就是被 OOM killer 干掉了。查看系统日志dmesg | grep -i oom journalctl -k | grep -i oom里面有 OOM killer 触发时各进程评分和被杀对象的完整记录。还有一个我踩过坑的操作很多人以为内存不够就手动sync; echo 3 /proc/sys/vm/drop_caches