1. 为什么在性能测试里绕不开 nmon 这个工具做性能测试这些年我见过太多人把注意力全放在压测工具上JMeter、Locust、wrk 玩得飞起脚本写得花里胡哨结果压测报告一出来只有响应时间和吞吐量两个维度老板问一句服务器到底扛不扛得住当场就哑火了。问题出在哪出在你只看到了结果没看到过程。压测工具告诉你的是应用层的表现而服务器本身的 CPU、内存、磁盘 IO、网络这些底层资源到底被吃掉了多少、瓶颈卡在哪个环节压测工具是看不到的。这时候就需要一个专门盯服务器资源的监控工具nmon 就是我在这个环节里用得最顺手的一个。nmon 全称是 Nigels Monitor最早由一位工程师为 AIX 系统开发后来移植到了 Linux 平台。它的核心价值就一句话用极低的资源开销把一台 Linux 服务器的 CPU、内存、磁盘、网络、文件系统等关键指标按固定频率采样并落盘事后可以回放分析。它不像 top 那样只能看实时快照也不像某些重量级监控平台那样需要部署一堆组件。一个二进制文件丢上去就能跑采集完把文件拉回本地用分析工具一打开整段时间的资源曲线一目了然。对于性能测试场景来说这种轻量采集、离线分析的模式简直是为压测量身定做的。这篇文章适合谁看如果你正在做性能测试需要一份能说清楚服务器在压测期间到底发生了什么的数据如果你是运维或者后端开发想快速定位线上服务的资源瓶颈又或者你只是单纯想学一个实用的 Linux 监控工具那这篇内容都能帮到你。我会从 nmon 的获取和部署讲起把采集策略怎么定、数据怎么读、常见坑怎么避结合我自己踩过的经验一点点拆开说。不讲虚的全是能直接抄作业的操作。2. nmon 的获取、部署与第一印象2.1 选对版本别在第一步就埋雷nmon 的获取方式有好几种但这里有个很多人忽略的坑nmon 是跟系统架构和发行版强相关的。你在 x86_64 的 CentOS 上能跑的二进制直接拷到 ARM 架构的服务器上就是一堆乱码报错。所以第一步不是急着下载而是先确认目标服务器的信息。我一般会先跑这几条命令摸清底细uname -m # 看架构x86_64 还是 aarch64 cat /etc/os-release # 看发行版和版本号 ldd --version # 看 glibc 版本这个很关键为什么要看 glibc 版本因为 nmon 的二进制是动态链接的如果目标机器的 glibc 版本比编译 nmon 时用的还低运行时会直接报GLIBC_2.xx not found。我遇到过一台老服务器系统几年没升级拿了个新版 nmon 上去死活跑不起来最后换了个针对老版本编译的才解决。所以稳妥的做法是优先用目标系统自带的包管理器安装比如在基于 RPM 的系统上可以尝试从官方源或可信的软件仓库获取在基于 Debian 的系统上也有对应的包。如果包管理器里没有再去下载对应架构和发行版的预编译二进制。提示下载 nmon 二进制后务必用chmod x赋予执行权限并且建议放在一个固定的目录比如/opt/nmon/下方便后续脚本调用。别随手丢在/tmp里有些系统会定期清理临时目录。2.2 三十秒跑通第一次采集部署其实简单到离谱nmon 是单文件程序没有任何依赖安装步骤。把二进制传上去、加执行权限就能直接跑。第一次用我建议先来个最简单的交互式采集感受一下它的界面./nmon回车之后你会看到一个字符界面的仪表盘上面有一排快捷键提示。按c显示 CPU按m显示内存按d显示磁盘按n显示网络按t显示 Top 进程。这个交互模式适合临时排查问题但你不可能一直盯着屏幕看性能测试动辄跑几十分钟甚至几小时所以真正干活靠的是后台采集模式。后台采集的典型命令长这样./nmon -f -s 10 -c 360 -m /opt/nmon/data这条命令拆开看-f表示按标准格式输出到文件文件名会自动带上主机名和时间戳-s 10表示每 10 秒采样一次-c 360表示一共采集 360 次也就是 3600 秒即一小时-m指定输出目录。跑起来之后它就在后台默默工作你可以继续做别的事采集结束后会在指定目录生成一个.nmon后缀的文件。这里有个经验值分享采样间隔-s到底设多少合适设太小比如 1 秒文件会非常大而且高频采样本身也会带来一点点开销设太大比如 60 秒又会漏掉短时间的资源尖峰。我的习惯是压测场景用 10 到 15 秒长时间趋势观察用 30 到 60 秒。如果是排查那种几秒钟的抖动才会临时降到 1 到 2 秒但采集时长也会相应缩短。2.3 采集文件里到底装了什么很多人采集完拿到那个.nmon文件一看是二进制或者特殊格式就不知道怎么办了。其实这个文件本质上是文本格式的你可以直接用head或者cat看个大概head -50 主机名_日期_时间.nmon你会看到里面是一行行的数据记录有CPU_ALL、MEM、DISKBUSY、NET这样的标记行后面跟着时间戳和一串数值。这些就是原始采样数据。直接看当然费劲所以 nmon 配套了一个分析工具通常叫 nmon analyser是一个表格宏文件把.nmon文件喂进去它会自动生成一堆图表CPU 使用率曲线、内存变化、磁盘繁忙度、网络吞吐等等。这一步是把冷冰冰的数字变成能讲故事的可视化报告后面我会专门讲怎么读这些图。3. 采集策略让数据真正对得上压测场景3.1 采集时机与压测节奏的对齐这是我觉得最容易被忽视、但又最影响分析质量的一点nmon 的采集窗口必须完整覆盖压测的各个阶段而且最好在时间轴上能和压测工具的记录对上。一次规范的性能测试通常分几个阶段预热、加压、稳态运行、减压、结束。如果你 nmon 只采集了稳态那一段那预热阶段的资源爬升、减压阶段的资源回落你就看不到了而这些恰恰能反映系统在负载变化时的弹性。我的做法是nmon 采集比压测脚本提前 1 到 2 分钟启动压测结束后再让它多跑 1 到 2 分钟。这样时间轴上前后都有余量分析时能清楚看到压测开始前系统是安静的压测一启动资源怎么爬压测停了资源怎么降。具体操作上我会写一个简单的调度脚本把 nmon 的启动和压测的启动串起来。比如#!/bin/bash # 启动 nmon 采集提前 60 秒 /opt/nmon/nmon -f -s 10 -c 600 -m /opt/nmon/data NMON_PID$! sleep 60 # 这里执行压测命令 # ... # 压测结束后再等 60 秒 sleep 60 # 如果采集次数没到可以手动结束 kill $NMON_PID这样采集文件的时间范围就天然包含了压测全过程。分析的时候你只要知道压测是从第 60 秒开始的就能在图表上精准定位。3.2 采样频率与采集时长的权衡计算前面提了采样间隔这里展开算一笔账让你心里有数。nmon 采集文件的大小大致和采样次数成正比。假设每次采样产生的数据量平均在 2KB 左右这个值随监控项多少浮动那么采样间隔采集时长采样次数预估文件大小10 秒1 小时360约 720 KB10 秒8 小时2880约 5.6 MB30 秒24 小时2880约 5.6 MB60 秒7 天10080约 20 MB可以看到即使采集一整天文件也就几 MB完全不用担心磁盘占用。所以文件大小基本不是限制因素真正的限制是你的分析需求。压测场景我坚持用 10 到 15 秒因为压测本身就是短时间高负载需要足够细的粒度才能捕捉到资源尖峰。而如果是长期容量规划比如观察一台服务器一周的资源趋势那 60 秒甚至更长就够了数据太细反而干扰趋势判断。注意-c参数是采集次数不是时长。很多人误以为-c 360是 360 秒其实是 360 次乘以采样间隔。用-s 10 -c 360才是 3600 秒。这个换算一定要搞清楚否则采集时长会差出好几倍。3.3 监控项的取舍不是越多越好nmon 默认会采集相当多的指标但你可以通过命令行参数控制采集哪些类别。比如-c控制 CPU-m控制内存-d控制磁盘-n控制网络-t控制 Top 进程。默认情况下它会把能采的都采了。那要不要精简我的观点是压测场景下默认全采就行别省。因为压测时你往往不知道瓶颈会出现在哪可能是 CPU可能是磁盘 IO也可能是网络。如果一开始就只采 CPU结果发现瓶颈在磁盘那就得重新压一遍浪费时间和资源。全采带来的额外开销微乎其微nmon 本身设计得就非常轻量对被测系统的影响通常可以忽略不计。但有一个例外Top 进程信息-t会记录当时占用资源最高的进程。这个在定位到底是哪个进程在吃资源时非常有用但它的数据量相对大一些。如果你采集时间特别长比如好几天可以考虑关掉它。压测场景我建议保留因为压测时经常需要确认是不是被测应用本身在消耗资源还是被别的进程干扰了。4. 读懂 nmon 数据从曲线里挖出瓶颈4.1 CPU 指标别只盯着一个使用率拿到 nmon analyser 生成的报告第一眼大家都会看 CPU 那张图。但 CPU 使用率这个指标坑特别多。nmon 给出的 CPU 数据里有几个关键列需要区分User%用户态 CPU 占用通常是应用程序消耗的。Sys%内核态 CPU 占用系统调用、IO 操作会推高这个值。Wait%等待 IO 的 CPU 时间占比这个值高说明 CPU 在等磁盘或网络。Idle%空闲。Steal%如果是虚拟机这个值表示被宿主机其他虚拟机抢走的 CPU 时间。我见过一个典型案例某次压测应用响应时间突然飙升但看 CPU 总使用率只有 40%很多人就下结论说CPU 不是瓶颈。结果仔细一看Wait% 高达 35%说明 CPU 大量时间在等 IO真正的瓶颈是磁盘。如果只看总使用率这个结论就完全错了。所以我的习惯是先看总使用率判断 CPU 是否紧张再看 User 和 Sys 的比例判断是应用问题还是系统调用问题最后看 Wait 判断是否存在 IO 等待。这三个维度结合起来才能对 CPU 状态有个准确判断。4.2 内存与 Swap被忽视的隐形杀手内存这块nmon 会给出物理内存和 Swap 的使用情况。很多人只看物理内存用了多少觉得没满就没事。但真正要命的是 Swap 的使用。Linux 有个特性叫内存回收当物理内存紧张时系统会把不常用的内存页换到 Swap 分区。这个过程本身会消耗 IO而且一旦应用需要访问被换出的内存就会触发缺页中断性能急剧下降。所以判断内存是否健康不能只看物理内存剩余还要看 Swap 有没有被大量使用。我的判断标准是这样的如果压测期间 Swap 使用量基本为 0那内存是健康的如果 Swap 开始增长说明物理内存已经不够用了系统在拆东墙补西墙如果 Swap 使用量持续上升且伴随大量 Swap In/Out那基本可以确定内存是瓶颈之一。这时候要么加内存要么优化应用的内存占用要么调整系统的内存回收策略。还有一个细节nmon 报告里的内存曲线有时候会看到物理内存使用率一直很高但系统运行正常。这其实是 Linux 的缓存机制在起作用文件缓存会占用大量内存但这是可回收的不算真正的内存压力。所以看内存不能只看用了多少要看可用多少以及 Swap 的活动情况。4.3 磁盘 IO繁忙度背后的真相磁盘指标里nmon 会给出每个磁盘设备的 Busy%繁忙度、Read/Write 速率、以及平均等待时间等。这里最容易误判的是 Busy%。Busy% 高说明磁盘一直在工作但不一定说明磁盘是瓶颈。因为磁盘的繁忙度取决于它的处理能力一块机械硬盘和一块固态硬盘同样 100% 繁忙能承受的 IOPS 差了几十倍。所以判断磁盘是否是瓶颈要结合 IOPS 和吞吐量一起看。我的经验是如果磁盘 Busy% 持续在 80% 以上同时应用的响应时间也在上升那磁盘很可能是瓶颈。这时候要进一步看是读多还是写多是随机 IO 还是顺序 IO。随机小 IO 对磁盘的压力最大机械硬盘在这种场景下 IOPS 可能只有一两百而固态硬盘能到几万。如果发现是随机小 IO 导致的瓶颈优化方向可能是加缓存、合并写入、或者换更快的存储介质。另外nmon 报告里如果有多个磁盘设备要分别看。有时候系统盘很闲但数据盘已经跑满了如果只看一个平均值就会漏掉真正的瓶颈点。4.4 网络带宽和连接数的双重考量网络指标相对直观nmon 会给出每个网卡的收发速率KB/s和包量。压测场景下网络瓶颈通常表现为带宽跑满或者包量过大导致处理不过来。但这里有个容易忽略的点网络瓶颈不一定在服务器这一端。如果压测客户端和被测服务器之间的网络带宽有限那服务器网卡可能还没跑满但实际吞吐已经上不去了。所以分析网络时要同时确认压测客户端的网络状况别把客户端的瓶颈算到服务器头上。还有一个细节是网络包的大小。如果应用传输的是大量小包那即使带宽没跑满网卡的处理能力PPS每秒包数也可能成为瓶颈。nmon 给出的包量数据可以帮你判断这一点。如果发现包量很高但带宽利用率不高那就要考虑是不是小包太多优化方向可能是合并请求、使用更高效的协议等。5. 实战中的坑与排查链路5.1 采集文件时间戳错乱时区惹的祸有一次我采集完数据拉回本地用分析工具打开发现时间轴对不上压测记录差了整整 8 小时。排查了半天最后发现是服务器时区和本地时区不一致导致的。nmon 记录的时间戳默认用的是服务器本地时间如果服务器设的是 UTC而你在东八区看自然就对不上。这个坑的解决办法有两个一是采集前先确认服务器时区用date命令看一眼必要时统一时区二是在分析时手动做时间偏移。我现在的习惯是采集前一定先跑date和timedatectl把时区信息记在采集备注里避免事后扯皮。5.2 采集进程被误杀后台运行的稳定性nmon 用-f后台模式跑的时候如果你是通过 SSH 连上去执行的一旦 SSH 会话断开nmon 进程可能会收到挂起信号而停止。这个坑我踩过不止一次采集到一半数据断了压测白做。解决办法是用nohup或者setsid让它脱离终端nohup /opt/nmon/nmon -f -s 10 -c 360 -m /opt/nmon/data 或者更稳妥的用screen或tmux开一个会话在里面跑。我个人的偏好是nohup加简单直接。采集启动后用ps -ef | grep nmon确认进程还在再放心断开。5.3 数据有了但看不出问题分析思路的建立还有一种情况更让人抓狂数据采集得好好的图表也生成了但就是看不出瓶颈在哪。这时候往往是分析思路出了问题而不是数据不够。我的排查链路是这样的先看应用层的表现响应时间、吞吐量、错误率确定问题发生的时间段然后回到 nmon 数据定位那个时间段按 CPU、内存、磁盘、网络的顺序逐个排查每个维度先看总体趋势再看细节指标如果某个维度有异常就深入看是哪个进程、哪个磁盘、哪个网卡导致的。这个链路的关键是先定位时间再定位资源最后定位具体对象一层层缩小范围。举个例子某次压测发现响应时间在某个时间点突然翻倍。我先在 nmon 里定位到那个时间点发现 CPU 的 Wait% 飙升说明有 IO 等待接着看磁盘发现某块盘的 Busy% 跑满再看是哪个进程在读写发现是日志写入过于频繁。问题定位到这一步解决方案就清晰了要么降低日志级别要么把日志写到更快的盘上要么做异步日志。5.4 采集开销本身的影响别让监控变成负担虽然 nmon 很轻量但在极端情况下比如采样间隔设到 1 秒、监控项全开、采集时间又很长它本身也会带来一定的开销。我做过一个粗略的对比测试在空闲系统上跑 nmon1 秒采样间隔下nmon 进程本身占用的 CPU 大概在 1% 到 2% 之间。这个开销在大多数场景下可以忽略但如果你测的是一个对资源极其敏感的应用或者服务器本身配置很低那就需要留意了。我的建议是正式压测前先做一次空载采集看看 nmon 自身对系统的影响有多大。如果影响在可接受范围内再开始正式采集。另外采样间隔不要盲目设太小10 到 15 秒对绝大多数压测场景已经足够。6. 把 nmon 数据变成能汇报的结论6.1 从原始数据到可视化报告nmon analyser 生成的报告虽然图表齐全但直接拿去汇报往往不够聚焦。我的做法是从报告里挑出和本次压测目标最相关的几张图重新组织成一个简洁的结论页。比如这次压测的目标是验证系统能否支撑 1000 并发那我就重点放三张图CPU 使用率曲线看是否接近饱和、内存和 Swap 曲线看是否有内存压力、磁盘 IO 曲线看是否有 IO 瓶颈。每张图下面配一句话结论比如CPU 峰值 75%未达瓶颈、Swap 全程为 0内存充足、磁盘 Busy% 峰值 92%存在 IO 压力。这样汇报对象一眼就能抓住重点。6.2 关键指标的阈值参考判断资源是否紧张需要一些阈值参考。下面这张表是我在实际工作中总结的常用参考值注意这些不是绝对标准要结合具体业务和硬件配置调整指标健康范围需关注危险CPU 总使用率 70%70% - 85% 85%CPU Wait% 5%5% - 15% 15%内存可用率 30%10% - 30% 10%Swap 使用0少量增长持续增长磁盘 Busy% 70%70% - 85% 85%网络带宽利用率 60%60% - 80% 80%这些阈值的作用是帮你快速判断而不是替代分析。比如 CPU 使用率 80% 不一定就是问题如果业务本身是计算密集型80% 可能是正常水平。关键是要结合压测目标和历史基线来看。6.3 一次完整的分析记录长什么样最后分享一个我实际分析时的记录模板你可以直接拿去用压测目标验证 XX 服务在 500 并发下的稳定性 采集配置nmon -f -s 10 -c 360覆盖压测前 1 分钟到压测后 1 分钟 压测时间14:00 - 14:50 资源表现 - CPU峰值 68%User 为主Wait% 平均 3%无异常 - 内存可用率稳定在 45%Swap 全程为 0 - 磁盘数据盘 Busy% 峰值 78%出现在 14:20 左右对应压测加压阶段 - 网络带宽利用率峰值 55%无丢包 结论系统在 500 并发下资源充足磁盘在加压阶段有短时压力但未成为瓶颈。建议后续测试 800 并发观察磁盘表现。这种记录方式的好处是数据、分析、结论一条线事后复盘或者交接都清清楚楚。nmon 给的是原始素材真正有价值的是你从素材里提炼出的判断。工具是死的分析思路是活的这也是我这些年做性能测试最深的体会。