nmon单机性能采样:从指标采集到故障复盘 1. 一台机器卡成幻灯片我才想起它先说个很典型的场景。半夜收到告警一台业务机器的负载从平时的 0.8 一路飙到 40 多SSH 还能连上但top敲下去光标闪半天不出结果ps aux也要卡十几秒。这种时候你其实特别被动重启服务能暂时把指标压下去可到底是内存被谁吃了、磁盘是不是在狂刷、还是某个 CPU 核心被单线程打满——全靠猜。更麻烦的是等你慢吞吞装好一套图形化监控问题早就自己消失了留下一句“当时确实很卡”谁也没法复现。nmon就是给这种场面准备的工具。它是跑在主机上的一个单文件采集器一个二进制丢上去就能跑不需要装依赖、不需要起服务、不需要连什么中心端。你让它采 CPU、内存、磁盘、网络、进程、文件系统这些指标它按照你给的间隔把数据写进一个二进制文件事后用配套的解析程序把这个文件转成表格甚至图形慢慢回看“卡的那三分钟到底发生了什么”。我把它理解成主机层面的“黑匣子”。它不像一些大盘方案那样讲究实时展示和集中管理它的定位非常明确轻量、离线、可以事后复盘。适合谁来学我觉得两类人收益最大——一类是要给线上机器做性能基线、又不想为单机场景上一整套体系的运维同学另一类是开发或测试需要在自己压测的时候抓一份细粒度数据不然压测报告里只有一条 QPS 曲线出了问题完全没法往下查。标题只写了“使用方法”但我认为光会敲几个参数远远不够。这个工具真正的门槛在三个地方知道该采哪些指标、采出来的数据怎么读、以及读出来之后怎么判断问题在哪儿。下面我按这个顺序展开中间会夹一些我自己趟过的坑全是文档里不太会写的部分。2. 为什么单机采样这件事非它不可在动手之前值得花点时间讲清楚它的位置。很多人第一次碰到nmon会下意识地拿它和那些常见的主机监控方案比然后觉得“界面太丑、还得自己转格式不如直接用现成的”。这个判断有它的道理但如果场景是“临时排查”和“事后复盘”结论会反过来。2.1 它的技术定位单文件采集无状态运行nmon的本质是一个用 C 写的采样程序干活方式非常朴素按照给定的时间间隔读一次内核暴露出来的计数器/proc下面的那些文件加上一些系统调用把数值追加写进自己的二进制文件。这里面有几个值得强调的细节它是单文件程序。整个工具就是一个可执行文件拷过去给上执行权限就能用不依赖运行时也不需要先起守护进程。这一点在受限环境里价值极大——有些生产机连包管理器都被裁掉了装个稍复杂点的采集组件能折腾半天。它是无状态的。没有常驻服务没有后台任务采完就退出。这意味着它不会在机器上留下一个长期跑着的进程也不会因为采集端自己崩溃而影响业务。用完把进程停掉机器就干净了。数据落本地。采集结果写在你指定的本地路径不涉及任何对外上报。对很多对数据流向有要求的环境来说这一点省掉了大量沟通成本。提示因为是二进制格式采集文件的体积非常小通常一小时的数据也就几百 KB 到几 MB 级别具体取决于你开了多少指标、间隔多长。长期挂在机器上不用担心把磁盘写满但路径别放在/tmp下面有些发行版的 tmpfs 重启就清空。2.2 和常见方案摆在一起比一比我把几类常见选择放在一起对照方便你判断自己该用哪个。注意这不是“谁更好”的排名而是场景匹配问题。方案类型典型形态实时性部署成本事后复盘能力适用场景单机采样工具如本篇单文件按间隔采样弱看文件极低强可回放细粒度临时排查、基线采集、压测取证系统自带命令交互式即时查看强零弱无历史快速扫一眼当前状态常驻采集组件中心端客户端上报汇聚强中到高中通常有采样降频长期趋势、规模化应用层埋点代码内埋点采集强高要改代码视实现而定业务逻辑内部问题这张表里最值得说的是“事后复盘能力”这列。交互式命令的问题在于它只呈现“此刻”而你真正需要答案的时刻往往是故障已经过去。常驻方案虽然存了历史但为了控制存储成本通常会把采样粒度拉长到分钟级恰恰是那种“瞬时的内存尖峰”或“几百毫秒的 IO 抖动”容易漏掉。nmon的强项就在这个缝里它可以把间隔压到 1 秒甚至更短只在你关注的这段时间里跑量不大精度够。2.3 一个容易忽略的成本采集本身会不会变成干扰我自己踩过一次。早期为了“信息更全”我几乎把所有指标都打开间隔设成 1 秒然后在一台 CPU 很紧的机器上长期挂着。后来对比发现采集进程本身的 CPU 占用在低配机器上能到 2%~5%对于一台本来就吃紧的机器这个数字不能再忽略——你相当于让它一边治病一边加重病情。所以选型不只是“选工具”还包括决定采集的强度。我的经验做法是长期基线采集用 30 秒或 60 秒间隔只看 CPU、内存、磁盘、网络四类核心项出问题时临时开短间隔1~5 秒并且限定采集时长比如只跑 15 分钟。这样既能抓到瞬时的抖动又不会自己造成新的负载。这个取舍的逻辑后面第 5 节还会展开讲怎么落在具体参数上。3. 上手前的十分钟准备比参数更重要的几件事装工具本身没什么可说的多数发行版的仓库里就有。真正让人卡住的是环境相关的琐碎细节这部分我按实际会遇到的顺序捋一遍。下面的命令都以常见 Linux 环境为例具体包名以你所在发行版的仓库为准。3.1 拿到可执行文件与验证安装之后第一件事是确认它能跑而且版本对得上# 以常见发行版仓库里的包为例具体包名请按你环境的仓库确认 sudo apt-get install nmon # 或者用你自己环境里的包管理方式 nmon -V # 看版本版本这一步别跳过。不同版本支持的参数和输出字段有差异尤其是“是否支持把磁盘、网络指标拆到独立视图”这类能力。我以前遇到过一个情况两份采集数据想放在一起对比结果一边是用老版本采的字段顺序不一致解析出来的表格列名对不上白白多花了一小时。验证完之后有个必做的动作先跑一次极短的采集看看文件能不能正常生成。别等到出了问题才发现权限不对、路径写不进去。nmon -f -s 2 -c 5 -m /var/log/nmon这条命令的含义是-f表示按文件方式采集后面会自动在文件名里带上时间戳-s 2表示每 2 秒采一次-c 5表示一共采 5 次-m指定输出目录。也就是说这条命令大约 10 秒后自动结束会生成一个类似主机名_年月日_时分.nmon的文件。跑完用ls -lh看一下正常应该是几十 KB 级别。注意-c是采集次数而不是时长这个和很多人的直觉相反。想跑 10 分钟、每 5 秒一次应该是-s 5 -c 120而不是写个“10m”。这两个参数算错会导致你本来想采一小时结果几十秒就结束了等你发现问题时机器已经恢复正常数据全废。3.2 输出目录与权限的坑-m指定的目录必须对执行用户可写。这个看起来是废话但实际操作里有两种常见翻车第一种是用普通用户跑目录选了只有 root 能写的路径。程序报了错但如果你把输出重定向到了别处很可能压根没看到报错以为采着呢最后发现那个时间点根本没有文件。第二种是文件系统空间的判断。采集文件本身不大但如果你在同一目录下还放着历史数据日积月累是有可能堆满的。我的做法是单独建一个目录比如/var/log/nmon然后在做长期采集时配合简单的清理规则只保留最近若干天的文件。还有一个和权限相关的隐性限制某些指标特别是涉及进程细节、部分块设备统计在非 root 下可能读不全。所以如果条件允许采集时用 root 跑能拿到的信息更完整如果必须用普通用户至少要清楚自己看到的进程视图是不全的。3.3 先搞清楚“采的是哪几类”nmon的交互界面用单字母切换视图这是它最标志性的操作方式。文件模式下的指标开关也是用这些字母来控制的。所以我建议在正式采集之前先在交互模式里熟悉一下这些字母免得后面看参数一头雾水。nmon # 不带参数直接运行进入交互界面进去之后按h会出帮助列表大致是这些不同版本略有差异按键视图内容我平时的关注度cCPU 使用含用户态、系统态、等待高m内存含缓存、交换区高d磁盘 IO读写速率、繁忙程度高n网络接口流量高t系统概要负载、进程队列中j文件系统使用率中k内核参数低p进程列表按资源排序中V虚拟内存与分页中交互界面上手最大的感受是“信息密度高但长得丑”。别被劝退它显示的东西其实就是后面文件里那堆字段。你在交互界面里能看懂的图转成文件之后照样能看懂。一个小提示交互模式下按键是切换再按一次同一个键通常是关闭该视图。多个视图可以叠加显示但全开会很花眼我的习惯是最多同时开三四个。4. 采集策略参数怎么配指标开哪些这部分是全文的核心。我把“参数”和“指标”分开讲因为它们是两个层面的事情-s、-c、-m决定什么时候采、采多久、放哪而视图字母决定采什么。4.1 时间维度间隔与次数的换算关系先把最基础的公式摆出来因为这是最容易算错的地方采集总时长 间隔秒数 × 采集次数 生成数据量 ≈ 采集次数 × 每次的字段量举个具体的-s 5 -c 720就是每 5 秒采一次共 720 次总时长 3600 秒 1 小时。如果要过夜采 8 小时、间隔 30 秒那就是-c 9608×3600÷30。不同间隔怎么选我有一张自己的经验表场景建议间隔理由临时抓瞬时抖动1~2 秒分钟级采样根本看不到尖峰压测过程中取证2~5 秒兼顾精度与数据量短期几小时巡检15~30 秒能看清趋势干扰小长期数天基线60~300 秒只为看增长趋势避免自扰这里有个我觉得值得强调的判断逻辑采样间隔不能大于你关心的现象的时间尺度。比如你怀疑某个定时任务每分钟跑一次、持续抖动两三秒那么采样间隔必须显著小于这个持续时间否则大概率每次都恰好落在抖动之间的平静期采出来一片祥和。反过来如果你只是想知道一周内内存有没有缓慢上涨1 秒间隔就纯属浪费——数据量放大 60 倍结论一点不变。4.2 指标开关-t、-T和那些字母文件模式下有两个常用参数控制内容量-t在输出中包含“top 进程”信息。这个对排查“到底是谁在吃资源”极其关键我基本必开。-T在输出中标记出消耗高的进程不同版本行为略有差异。-A采集磁盘相关指标部分版本用它控制磁盘数据是否包含。以及按照视图字母开启其他项比如-N对应网络、-s已经用于间隔所以别混。具体可用开关要看nmon -h的输出别凭记忆写。我的习惯配置大概是这样的# 采集 1 小时5 秒一次包含进程信息输出到指定目录 nmon -f -t -s 5 -c 720 -m /var/log/nmon对于需要更全指标的排查场景可以再加更多开关但要记住第 2.3 节说的每多开一类指标采集开销就往上走一档在低配机器上要掂量。提示命令行参数在不同版本之间不完全一致尤其是某些开关在较老版本里不存在。我的做法是先用nmon -h看一眼把可用的开关记在笔记里不要复制网上抄来的长命令直接用。4.3 进程信息为什么值得单独说-t这个开关我认为是被低估的。很多人采了一堆 CPU、内存曲线看到负载高然后卡在“到底是哪个进程”上——因为没开进程采集只能回看当时的曲线叹口气。打开之后输出里会有一块按资源排序的进程快照。虽然它的粒度跟着采样间隔走不是连续的但足够回答“那个时间点谁在前面”这个问题。我的经验是开进程采集几乎是零成本的判断力提升唯一要注意的是进程多的机器上字段会变多文件略微大一点这个代价完全可以接受。5. 数据怎么读从二进制文件到能看懂的图采完只是第一步采集文件本身是二进制的直接看是乱码。要用配套的解析程序把它转成人能读的格式。5.1 解析工具的选择与常见报错常见的解析方式有两类一类是基于表格的解析程序把数据转成电子表格格式一类是绘图脚本直接出折线图。前者适合精确定位“某一秒的数值”后者适合整体感受趋势。# 表格类解析输出为电子表格格式具体命令名以你环境中的为准 nmon2csv 主机名_250101_1200.nmon这一步最常见的报错是解析程序找不到或版本不匹配导致字段错位。典型表现是表格第一行显示的时间列全部变成奇怪的值或者某些列整列是空的。碰到这个先确认采集端和解析端是不是同一套版本。跨版本解析失败是很常见的事尤其当你把老机器采的文件拿到新环境里分析时。第二种常见问题是电子表格的字符集。某些解析产物在不同的办公软件里打开编码识别不一致会出现乱码。这个不难解决导入时手动指定编码一般就好。5.2 用图说话把一小时的曲线看明白如果不想在表格里翻数字转成图会直观很多。绘图脚本通常需要电子表格解析工具的支持本质上是在生成有时序数据的图表文件。我的实际用法是先出总览图看哪条曲线明显异常然后再回到表格里精确看具体时刻。这个“先粗后细”的顺序很重要反过来做会非常低效——你在一万行数字里找异常不如在图上找一个尖峰再定位。看曲线的时候我固定看这几对关系CPU 的用户态和系统态。系统态占比高通常说明内核在忙可能是系统调用频繁、IO 压力大、上下文切换多用户态高则是应用自己在算。CPU 等待时间和磁盘繁忙度。等待高但磁盘不忙要怀疑是不是其他原因导致的阻塞两者同时高基本可以确定是 IO 瓶颈。内存的实际使用和缓存。这块最容易被误读见下一节。网络流入流出和重传如果有。5.3 内存那张图我见过太多人读错这是我认为最值得单独讲的一点因为它几乎是人人都踩过的坑。在主机监控里“可用内存少”经常被当成严重问题上报但实际可能完全正常。原因是文件系统缓存系统会把空闲内存拿来做缓存以加速读写当应用需要内存时这部分是可以被回收的。所以判断内存是否吃紧核心看的不是“剩余多少”而是可用量考虑可回收部分之后和交换区的活动。具体到nmon的输出上我的阅读顺序是先看可用内存的趋势是不是持续下降而不是围绕某个值波动。再看交换区有没有实际的换入换出。只有发生了换页才说明真的在扛不住地往外挪。最后看进程视图里谁占得多验证判断。如果只看“剩余内存低”就急着重启服务很可能重启完发现指标依然那样因为缓存又被重新占满了。这一点如果没搞清楚排查会反复绕圈。还有一个细节某些虚拟化环境下机器内部看到的内存和宿主机分配之间存在差异曲线会出现一些你从内部无法解释的台阶。碰到这种情况别只盯着内部数据要结合宿主侧的信息看。6. 排查链路三个真实场景的走法光有工具和指标还不够真正决定效率的是排查的顺序。我按三种最常见的症状把完整的判断链路写出来你可以照着套。6.1 负载高但 CPU 不忙先怀疑 IO 和进程状态这种情况很经典负载数字很高但 CPU 使用率看起来只有二三成。很多人第一反应是“负载统计不准”其实往往是真的——负载统计的是可运行和不可中断状态的进程数而那些卡在 IO 上的进程会算进去却几乎不吃 CPU。排查顺序我是这样走的打开磁盘视图看读写速率和繁忙程度。如果繁忙度长时间接近满值基本可以锁定。打开 CPU 视图看等待时间占比。等待高是佐证。打开进程视图找出处于不可中断状态、或者 IO 读数最高的进程。结合业务判断是数据量突增、是某个批量任务在跑、还是存储侧变慢了。这三步所需的数据都能在一次采集里拿到前提是你开了磁盘和进程视图。所以再强调一次平时采集就把这几类都打开别等到出事才发现数据里没有磁盘那一块。6.2 内存缓慢上涨区分泄漏和缓存增长这是一个需要长期数据才能下结论的问题短时间采集看不出来。做法是跑一段长基线比如 24 小时、60 秒间隔然后看可用内存的趋势线。判断逻辑可以整理成这个顺序观察到的现象更可能的解释下一步动作可用内存在某个区间内波动正常的缓存行为不用处理可用内存单调下降交换区无活动可能是应用侧持有增长结合进程视图定位看堆或对象数可用内存下降且交换区有换页已经出现内存压力优先处理考虑扩容或限制内存平稳但进程被终止可能是其他限制如组配额换方向排查不要死盯总量这个表的价值在于它能帮你避免“看到内存紧张就扩容”这种粗暴反应。有些情况下扩容只是把问题推迟了因为泄漏的速度不变只是起点变高。6.3 网络看起来正常但服务超时看接口而不是看总量网络指标很容易看漏。总量图看起来流量不高但服务就是超时这时候要看的不是“带宽用了多少”而是连接的分布和错误计数。我的做法是先在网络视图里确认是哪个接口有流量多网卡机器上经常看错接口然后关注错误、丢弃这类计数是否在增长。持续增长的错误计数往往对应链路或配置层面的问题而不是应用逻辑的问题。另外还有一个经常被忽略的点采集间隔和超时时间的关系。如果你的服务超时是几百毫秒级而采样间隔是 30 秒那么网络视图几乎是没用的——它只能告诉你“这半分钟平均怎么样”。这种场景下必须把间隔压下来或者换用更细粒度的抓取方式。7. 那些文档里不会写的实操心得最后这部分是我自己用下来觉得最值钱的东西都是踩过之后才明白的。7.1 采集文件一定要带上下文单看一个.nmon文件你只能看到指标看不到“当时在干什么”。我的习惯是在采集目录里同时放一个同名的文本备注写清楚采集时间、机器角色、当时在做什么操作压测发布批量任务、有没有做变更。这个习惯救过我很多次。有一次对比两份曲线一份平滑一份有规律尖峰我差点去查应用代码结果翻到备注才发现尖峰那份正好是备份任务在跑的时间段一切正常。数据本身不带语义语义得你自己补。7.2 用“对照采集”代替“单点采集”如果你的目的是验证某个改动有没有效果单采一份几乎没有说服力。正确做法是改动前后各采一份、时长和间隔完全一致然后放在一起对比。对照采集有三个要点间隔一致否则曲线密度不同看不出差异、时长足够至少覆盖一个完整的业务周期、环境尽量一致别在业务高峰和低谷各采一份然后下结论。做到这三点对比出来的结论才站得住。7.3 别忘了清理和归档长期挂采集的话文件会累积。我的做法是靠文件名里的时间戳做归档超过一定天数的文件打包压缩后挪到别处或者直接按保留策略删除。注意别用太激进的删除规则我曾经写错过一次通配符把刚采的文件一起清掉了只能重采。另外如果是为了事故复盘保留数据建议在事故结束后第一时间把相关文件拷贝出来单独存放。机器上的目录经常会被顺手清理等你要复盘的时候发现文件没了那种感觉相当难受。7.4 采集中断的处理nmon在采集中如果被中断比如进程被杀、机器重启文件可能会缺少尾部数据甚至出现解析异常。我的经验是采集期间别对那个文件做任何操作也不要放在会被其他程序轮转的目录里。如果真的中断了通常前面已经写入的部分还能解析只是最后一段缺失处理时注意别把缺失当成“指标掉到零”。这个坑很隐蔽曲线最后一段突然掉到零很容易被误读成“服务停了”实际上只是采集断了。看曲线的时候永远先确认采集本身是否完整。8. 关于这件事我自己的几句体会用久了会发现nmon这类工具的价值不在“功能多”而在“随时能用、用完就走、事后可查”。它不适合当长期大盘的核心但在“我现在就要弄清楚这台机器刚才怎么了”这种时刻它几乎没有替代品。我个人的固定动作是任何一台新上线的机器先做一次短时基线采集存着任何一次发布或压测前后各采一份任何一次线上抖动第一反应是先挂一个短间隔采集再动手处理。这三个动作不花什么成本但能让后面每一次“到底为什么”的问题都有据可查。真正需要练的其实是读图那部分。工具的参数半小时就能记住但“看到等待时间高就知道往 IO 方向想”“看到内存低先看缓存和交换”这些判断是靠一次次数出来的。我的建议是别等出事才用平时就在自己机器上采一份对着曲线把每个字段的含义弄明白。等到真出问题的时候你的眼睛会比你想象的快。