Performance Monitoring Tools
Linux 内存与性能监控
Linux 系统中用于监控性能的核心命令行工具,从高层级的系统概览到深入的进程级分析。
第一部分:高层级系统概览
这些工具可以让你快速了解系统的健康状况、运行时间和资源利用率的总体情况。
1. uptime
- 快速系统健康检查
uptime
命令是检查系统当前负载和已运行时间的最简单方法。
- 作用:显示当前时间、系统已运行时长、登录用户数以及过去 1、5、15 分钟的系统平均负载。
- 目的:快速评估系统是否近期重启过,以及当前是否处于高负载状态。
基本语法与用法
1 | uptime |
输出示例:
1 | 14:21:33 up 12 days, 3:42, 2 users, load average: 0.07, 0.14, 0.11 |
输出详解
- **
14:21:33
**:当前的系统时间。 - **
up 12 days, 3:42
**:系统自上次启动以来已运行的总时长。如果时长很短,可能意味着系统发生了意外重启或崩溃。 - **
2 users
**:当前登录到系统的用户会话数。 - **
load average: 0.07, 0.14, 0.11
**:这是最关键的指标,三个数字分别代表过去 1 分钟、5 分钟、15 分钟的平均负载。- 定义:在特定时间段内,处于可运行状态 (Running) 或 不可中断睡眠状态 (Uninterruptible Sleep / Waiting for I/O) 的平均进程数。
- **解读方法 (结合 CPU 核心数)**:
- 首先,通过
nproc
或lscpu
命令获取 CPU 核心数。 - Load < 核心数:系统有空闲资源,负载轻松。例如,在 4 核系统上负载为 0.07,表示非常空闲。
- Load ≈ 核心数:系统资源已接近饱和。
- Load > 核心数:系统已过载,进程需要排队等待 CPU 时间,表明存在性能瓶瓶颈。
- 首先,通过
常用选项
- **
-p, --pretty
**:以更易读的格式显示运行时长。1
2uptime -p
# 输出: up 12 days, 3 hours, 42 minutes - **
-s, --since
**:显示系统启动的确切日期和时间。1
2uptime -s
# 输出: 2025-08-05 10:39:44
底层机制
uptime
从 /proc
虚拟文件系统获取信息:
- 运行时长来自
/proc/uptime
。 - 平均负载来自
/proc/loadavg
。
2. free
- 内存使用快照
free
命令提供了系统物理内存 (RAM) 和交换空间 (Swap) 使用情况的快速摘要。
概念与用途
- 作用:显示物理内存和交换分区的总量、已用量、空闲量等信息。
- 目的:快速判断系统内存是否紧张,以及是否过度依赖交换空间。
- 数据来源:通过解析
/proc/meminfo
文件来提供一个汇总视图。
基本语法与用法
1 | free |
输出示例 (单位:KB):
1 | total used free shared buff/cache available |
输出详解
- **
total
**:总安装的物理内存或交换空间大小。 - **
used
**:已使用的内存。这个值的计算方式是total - free - buff/cache
。 - **
free
**:完全未被使用的内存。 - **
shared
**:被多个进程共享的内存,主要用于tmpfs
等。 buff/cache
:被内核用作缓冲区 (buffers) 和 页缓存 (cache) 的内存。Linux 会积极地将空闲内存用于缓存,以加速文件和磁盘 I/O 操作。这部分内存在应用程序需要时可以被立即释放。available
:这是判断内存压力的最重要指标。它估算了在不发生交换(swapping)的情况下,可供新应用程序使用的内存大小。它约等于free + 可回收的 buff/cache
。
核心理念:在 Linux 中,
used
内存很大是正常现象,因为“空闲的内存就是浪费的内存”。只要available
值充足,系统就不算内存紧张。
常用选项
-h, --human
: 以人类可读的单位 (GB, MB, KB) 显示。这是最常用的选项。1
free -h
-b
,-k
,-m
,-g
: 分别以字节 (Bytes)、KB、MB、GB 为单位显示。-s N
: 每 N 秒刷新一次数据,用于持续监控。1
2
3
4
5free -h -s 2
```* **`-c N`**: 与 `-s` 配合使用,表示刷新 N 次后退出。
```bash
# 每 2 秒刷新一次,总共刷新 5 次
free -h -s 2 -c 5
运维实例
- 判断内存瓶颈:如果
available
的值非常小,并且Swap
的used
值持续增加,说明物理内存已不足,系统开始使用硬盘作为虚拟内存,这将严重影响性能。 - 自动化监控脚本:可以编写脚本,当
available
内存低于某个阈值(如 500MB)时自动报警。
1 |
|
代码解析:
- free -m: 以 MB 为单位显示内存信息。
- |: 管道符,将前一个命令的输出作为后一个命令的输入。
- awk ‘/^Mem:/ {print $7}’: awk 是一个强大的文本处理工具。
- ‘/^Mem:/‘: 匹配以 “Mem:” 开头的行。
- {print $7}: 打印该行的第 7 列(字段),在 free -m 的输出中,这通常是 available 列。
可以将这样的脚本加入到 cron 定时任务中,实现周期性的自动内存监控。
第二部分:综合性能监控
这些工具提供了更全面的视图,结合了 CPU、内存、I/O 等多个维度的信息。
3. vmstat
- 虚拟内存统计
vmstat
(Virtual Memory Statistics) 是一个功能强大的工具,可以报告关于进程、内存、分页、块 I/O、中断和 CPU 活动的信息。
概念与用途
- 作用:动态地实时显示系统各项资源的运行状态,尤其适用于分析系统是否存在性能瓶颈。
- 目的:判断系统瓶颈是来自 CPU、内存还是 I/O。
基本语法与用法
1 | # 每 2 秒刷新一次,共刷新 5 次 |
输出示例:
1 | procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- |
输出详解
procs
(进程)r
(Run queue): 正在运行或等待 CPU 的进程数。如果这个值长期大于 CPU 核心数,说明 CPU 存在瓶颈。b
(Blocked): 处于不可中断睡眠状态的进程数,通常是在等待 I/O。如果这个值较大,可能表示 I/O 瓶颈。
memory
(内存)swpd
: 已使用的交换空间大小 (KB)。free
: 空闲的物理内存大小 (KB)。buff
: 用于块设备 I/O 的缓冲区大小 (KB)。cache
: 用作文件系统缓存的页缓存大小 (KB)。
swap
(交换)si
(Swap In): 每秒从交换空间换入到内存的数据量 (KB/s)。如果该值不为 0,说明内存不足。so
(Swap Out): 每秒从内存换出到交换空间的数据量 (KB/s)。如果该值不为 0,说明内存严重不足。
io
(块设备)bi
(Blocks In): 每秒从块设备读取的数据块数 (通常为 KB/s)。bo
(Blocks Out): 每秒写入到块设备的数据块数 (通常为 KB/s)。
system
(系统)in
(Interrupts): 每秒的中断次数。cs
(Context Switches): 每秒的上下文切换次数。频繁的上下文切换会消耗大量 CPU 时间。
cpu
(CPU 使用率百分比)us
(User): 用户态代码消耗的 CPU 时间百分比。sy
(System): 内核态代码消耗的 CPU 时间百分比。如果该值过高,说明系统调用开销大。id
(Idle): CPU 空闲时间百分比。wa
(Wait I/O): CPU 等待 I/O 完成的时间百分比。如果该值过高,表示 I/O 是系统瓶颈。st
(Steal): 在虚拟化环境中,被宿主机 (Hypervisor) 偷走的 CPU 时间百分比。
常用选项
-a, --active
: 显示活动和非活动内存。-S M
: 以 MB 为单位显示内存相关信息。-t, --timestamp
: 在每行输出后添加时间戳。-d, --disk
: 显示详细的磁盘统计信息。-s, --stats
: 显示自系统启动以来的各项事件计数器和内存统计的汇总表。
您提的建议非常好!为 vmstat
补充更多具体的运维场景和实例,能极大地提升这篇指南的实用价值。vmstat
的魅力就在于它能通过几个简单的数字揭示系统层面的复杂问题。
我将完全重写 vmstat
的“运维应用场景”部分,加入多个详细的、分步骤的诊断案例和更具代表性的监控脚本。
实例
vmstat
的输出信息非常密集,是排查系统级性能瓶颈的利器。运维工程师通常通过观察关键指标的变化趋势来诊断问题。
场景一:诊断 CPU 瓶颈
问题现象:应用响应缓慢,
top
命令显示总体 CPU 使用率很高,%idle
接近 0。诊断命令:
1
2# 每秒刷新一次,持续观察
vmstat 1关键指标与分析:
- 观察
procs
->r
列:- 分析:
r
列表示正在运行或等待 CPU 的进程数。如果这个值持续地、显著地大于您的 CPU 核心数(通过nproc
命令查看),则表明 CPU 已经成为瓶颈,有大量进程在排队等待执行。
- 分析:
- 观察
cpu
->us
和sy
列:- 分析:
- 如果
%us
(用户态) 长期很高 (例如 > 70%),说明是应用程序本身(如计算密集型任务、死循环)消耗了大量 CPU。 - 如果
%sy
(内核态) 长期很高 (例如 > 30%),说明是内核或系统调用占用了大量 CPU,可能是 I/O 操作频繁、驱动程序问题或系统调用开销过大。
- 如果
- 分析:
- 观察
结论与下一步:
- 确认 CPU 瓶颈后,应使用
pidstat -u 1
或perf top
来定位具体是哪个进程或函数在消耗 CPU 资源。
- 确认 CPU 瓶颈后,应使用
场景二:诊断 I/O 瓶颈
- 问题现象:系统响应迟钝,但
top
显示 CPU 的%idle
很高,利用率并不饱和。 - 诊断命令:
1
vmstat 1
- 关键指标与分析:
- 观察
cpu
->wa
列:- 分析:
wa
(Wait I/O) 表示 CPU 等待 I/O 操作(通常是磁盘读写)完成的时间百分比。如果这个值持续偏高 (例如 > 20%),强烈暗示系统的瓶颈在 I/O 子系统,CPU 大部分时间都在“无所事事”地等待硬盘响应。
- 分析:
- 观察
procs
->b
列:- 分析:
b
列表示被阻塞、等待 I/O 的进程数。如果这个值长期大于 0,也佐证了 I/O 存在瓶颈。
- 分析:
- 观察
io
->bi
和bo
列:- 分析:这两列显示了块设备(磁盘)的读写活动量。如果
bi
(读) 或bo
(写) 的数值很大,说明正有大量的磁盘操作,这与高%wa
是一致的。
- 分析:这两列显示了块设备(磁盘)的读写活动量。如果
- 观察
- 结论与下一步:
- 确认 I/O 瓶颈后,应使用
iostat -x 1
或iotop
来定位是哪个磁盘、哪个进程在进行大量的读写操作。
- 确认 I/O 瓶颈后,应使用
场景三:诊断内存压力与交换活动
- 问题现象:系统突然变得极度缓慢,甚至 SSH 连接都可能卡顿。
- 诊断命令:
1
vmstat 1
- 关键指标与分析:
- 观察
swap
->si
和so
列:- 分析:
si
(Swap In) 和so
(Swap Out) 分别表示从磁盘换入内存和从内存换出到磁盘的数据量。只要这两列出现非零值,就必须高度警惕。这表明物理内存已经不足,内核被迫使用速度慢上千倍的硬盘来充当内存。频繁的交换是系统性能的头号杀手。
- 分析:
- 观察
memory
->free
和swpd
列:- 分析:
free
列的值持续走低,同时swpd
(已用交换空间) 的值在增加,这是内存不足的直接证据。
- 分析:
- 观察
- 结论与下一步:
- 确认系统在进行频繁交换后,应立即使用
free -h
查看总体内存情况,并用pidstat -r 1
或top
(按内存排序)找出消耗内存最多的“罪魁祸首”,考虑优化程序或增加物理内存。
- 确认系统在进行频繁交换后,应立即使用
场景四:自动化脚本监控
除了手动排查,vmstat
也常用于自动化监控脚本,对关键指标设置阈值进行告警。
示例:监控系统是否在进行磁盘交换 (Swap Out)
1 |
|
脚本解析:
vmstat 1 2
: 运行两次的原因是vmstat
的第一行输出是系统自启动以来的平均值,没有实时参考意义。第二行及以后的输出才是基于采样间隔的瞬时值。- 这个脚本可以集成到监控系统中,一旦发现系统开始进行磁盘交换,就能立即触发告警,让运维人员及时介入处理。
4. dstat
- 全能的系统资源统计工具
dstat
是一个功能极其丰富的工具,它可以看作是 vmstat
, iostat
, netstat
和 ifstat
等命令的组合体,并增加了许多额外功能。
概念与用途
- 作用:实时、模块化地监控系统各项资源,包括 CPU、磁盘 I/O、网络、内存分页等。
- 特点:
- 模块化:可以自由组合要监控的指标。
- 彩色输出:结果直观,易于阅读。
- 插件系统:可扩展监控更多应用,如 MySQL、NFS 等。
- CSV 导出:方便后续进行数据分析和绘图。
基本语法与用法
1 | # 默认模式,每秒刷新一次 |
输出示例:
1 | ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system-- |
输出详解 (默认模式)
total-cpu-usage
: CPU 使用情况 (usr
,sys
,idl
,wai
,stl
),与vmstat
类似。dsk/total
: 磁盘 I/O 汇总 (read
,writ
),单位默认为 Bytes。net/total
: 网络流量汇总 (recv
,send
),单位默认为 Bytes。paging
: 分页活动 (in
=page in,out
=page out)。- **
system
**:系统事件 (int
=中断,csw
=上下文切换)。
常用选项 (模块化组合)
dstat
的强大之处在于通过选项组合监控内容:
-c
: 显示 CPU 统计 (--cpu
)。-m
: 显示内存统计 (--mem
)。-d
: 显示磁盘 I/O 统计 (--disk
)。-n
: 显示网络统计 (--net
)。-l
: 显示负载均值 (--load
)。-g
: 显示分页统计 (--page
)。-y
: 显示系统统计 (--sys
)。--top-cpu
: 显示消耗 CPU 最多的进程。--top-io
: 显示进行最多 I/O 操作的进程。--output <file.csv>
: 将输出结果保存为 CSV 文件。
组合示例:
1 | # 同时监控 CPU、内存、磁盘和网络,每 2 秒一次,共 10 次 |
dstat
的最大优势就是其模块化和灵活性,非常适合在运维一线快速、全面地定位问题。
dstat实例
dstat
是运维工程师的“瑞士军刀”,因为它能用一条命令替代多个传统工具,并以高度可读的方式呈现信息。以下是一些典型的实战场景。
场景一:系统性能“全面体检”
这是最常用的场景,用于快速了解系统当前是否存在明显的性能瓶颈。
问题现象:接到报告说“服务器有点慢”,但没有具体指向。
诊断命令:
1
2# 显示最核心的指标:CPU, 磁盘, 网络, 系统负载, 内存
dstat -cdnlmy或者使用一个更紧凑的版本:
1
2# 每秒刷新,显示 CPU, 磁盘, 网络和系统事件
dstat -cdnsy 1分析思路:
- 看 CPU (
-c
):wai
(I/O 等待) 是否过高?sys
(内核态) 是否异常? - 看磁盘 (
-d
):read
或writ
是否有巨大的流量? - 看网络 (
-n
):recv
或send
是否流量饱和或有异常突发? - 看系统 (
-y
):csw
(上下文切换) 是否过高,暗示进程竞争激烈? - 看内存 (
-m
):used
是否接近total
,free
是否极低?(虽然dstat
没有available
列,但可以初步判断)
- 看 CPU (
结论:通过这一条命令,你可以在几秒钟内对系统的 CPU、磁盘、网络三大瓶颈来源做出初步判断,然后决定下一步使用哪个更专业的工具(如
iostat
,pidstat
)进行深入分析。
场景二:定位消耗资源最多的“元凶”进程
当系统负载很高时,需要快速找出是哪个进程在消耗资源。
- 问题现象:
uptime
显示负载很高,top
看到有进程 CPU 或 I/O 占用率高。 - 诊断命令:
1
2# 实时显示消耗 CPU、内存和 I/O 最多的进程
dstat --top-cpu --top-mem --top-io - 分析思路:
--top-cpu
: 直接列出当前消耗 CPU 时间最多的进程名和其 CPU 使用率。--top-mem
: 列出占用物理内存最多的进程。--top-io
: 列出进行最多磁盘 I/O 操作的进程。
- 结论:这个组合命令几乎可以立即锁定导致系统变慢的“罪魁祸首”,省去了在
top
、iotop
、htop
之间来回切换的麻烦。
场景三:分析网络应用与磁盘 I/O 的关联
在处理数据库、Web 服务器或存储服务时,经常需要分析网络流量是否导致了大量的磁盘 I/O。
问题现象:一个文件服务器或数据库服务器,在网络流量增大时,磁盘响应变慢。
诊断命令:
1
2# 同时监控网络流量、TCP 连接数和磁盘的详细 I/O
dstat -ntd --tcp-states # 有的版本可能是 --tcp如果你还想看具体是哪个磁盘分区在忙,可以这样:
1
2# 监控所有网络接口、TCP 连接状态和 sda1、sdb1 两个分区的 I/O
dstat -nt --disk-util sda1,sdb1 2分析思路:
- 观察关联性:当网络
recv
或send
流量 (-n
) 飙升时,磁盘的read
或writ
(-d
) 是否也随之飙升? - **观察 TCP 状态 (
--tcp-states
)**:EST
(Established) 连接数是否异常增多?TMW
(Time Wait) 状态是否过多,占用了大量端口资源?
- 观察关联性:当网络
结论:通过这种方式,可以直观地看到网络请求和后端存储压力之间的因果关系,对于优化应用缓存、调整网络参数非常有帮助。
场景四:数据采集与事后分析
当需要对一个长时间运行的任务进行性能分析,或者需要向他人提供性能报告时,dstat
的 CSV 导出功能非常有用。
问题现象:需要对一个数据迁移任务(持续数小时)的资源消耗情况进行记录,以便后续制作性能图表。
诊断命令:
1
2
3
4# 每 10 秒采样一次,持续采集 360 次(即 1 小时)
# 监控 CPU, 内存, 磁盘, 网络, 负载,并添加时间戳
# 结果输出到 report.csv 文件中
dstat -cdnmly --time --output /tmp/report.csv 10 360分析思路:
- 任务运行期间,让脚本在后台执行。
- 任务结束后,
report.csv
文件就是一个标准的 CSV 格式文件。 - 你可以用 Excel、Google Sheets、Python (Pandas) 或 Gnuplot 等工具导入这个文件,轻松地绘制出 CPU 使用率、磁盘 I/O 流量等随时间变化的曲线图。
结论:
dstat
不仅是实时诊断工具,也是一个轻量级的数据采集器,非常适合性能基准测试和报告制作。
通过这些具体的、组合式的实例,可以看出 dstat
在实际运维工作中的强大灵活性和高效性。它真正做到了“一器在手,全局我有”。
第三部分:专项深度分析
当发现某个特定领域(如 I/O 或 CPU)存在问题时,可以使用这些专业工具进行深入分析。
5. iostat
- 磁盘 I/O 性能分析
iostat
(Input/Output Statistics) 专注于监控系统的磁盘 I/O 子系统和 CPU 使用率。
概念与用途
- 作用:提供详细的块设备 (磁盘) I/O 活动和 CPU 统计。
- 目的:定位磁盘性能瓶颈,分析数据库、文件服务器等 I/O 密集型应用的性能问题。
- 来源:属于
sysstat
软件包,可能需要手动安装 (sudo apt install sysstat
)。
基本语法与用法
1 | # 每 2 秒刷新一次,显示扩展统计信息 |
输出示例 (使用 -x
选项):
1 | avg-cpu: %user %nice %system %iowait %steal %idle |
输出详解
avg-cpu 部分
- %user:用户态 CPU 占用(应用程序消耗 CPU 时间)
- %nice:被调整优先级 (nice) 的进程消耗 CPU
- %system:内核态 CPU 占用(系统调用、驱动等)
- %iowait:CPU 空闲,但在等待 I/O 完成。这是
iostat
中最需要关注的 CPU 指标。如果该值持续偏高,说明磁盘可能是系统的主要瓶颈。 - %steal:虚拟化环境下,被 hypervisor 占用的 CPU 时间
- %idle:CPU 空闲时间(不做事、也不等 I/O)
Device 部分(磁盘指标,设备 I/O 部分 - 使用
-x
扩展模式)读写速率
- r/s:每秒读请求数(读 IOPS)
- rkB/s:每秒读数据量(KB/s)
- w/s:每秒写请求数(写 IOPS)
- wkB/s:每秒写数据量(KB/s)
- d/s:每秒 discard 请求数(主要用于 SSD)
- dkB/s:每秒 discard 数据量
请求合并
- rrqm/s:每秒被合并的读请求数
- %rrqm:被合并的读请求百分比
- wrqm/s:每秒被合并的写请求数
- %wrqm:被合并的写请求百分比
- drqm/s:每秒被合并的 discard 请求数
- %drqm:被合并的 discard 请求百分比
等待时间与请求大小
- r_await:平均读请求等待时间(ms,含排队+执行)
- rareq-sz:平均每次读请求大小(KB)
- w_await:平均写请求等待时间(ms)
- wareq-sz:平均每次写请求大小(KB)
- d_await:平均 discard 请求等待时间
- dareq-sz:平均 discard 请求大小
- f/s:每秒 flush 请求数(文件系统落盘)
- f_await:flush 请求平均等待时间
队列与利用率
- aqu-sz:平均 I/O 队列长度
- %util:磁盘利用率,接近 100% 表示磁盘已满负荷
iostat
是诊断磁盘 I/O 性能问题的绝对主力工具。
iostat
命令行参数详解
iostat
的参数可以分为几类:控制输出内容、控制输出格式和控制采样方式。
基本语法: iostat [选项] [间隔秒数] [次数]
1. 控制输出内容的选项
-c
: (CPU)- 单独显示 CPU 使用率统计报告。默认情况下,
iostat
会同时显示 CPU 和设备信息,使用此选项可以只关注 CPU。
- 单独显示 CPU 使用率统计报告。默认情况下,
-d
: (Device)- 单独显示块设备(磁盘)的使用率统计报告。
-N
: (Network Filesystem)- 显示网络文件系统 (NFS) 的统计信息。
-h
: (Human-readable)- 以人类可读的格式(例如
K
,M
,G
)显示输出。这个选项非常实用,可以避免去数零。
- 以人类可读的格式(例如
-k
: (Kilobytes)- 以 KB 为单位显示统计数据(这是默认值)。
-m
: (Megabytes)- 以 MB 为单位显示统计数据。
-p [device | ALL]
: (Partition)- 显示块设备及其所有分区的统计信息。你可以指定某个设备(如
-p sda
)或使用ALL
显示所有设备及其分区。
- 显示块设备及其所有分区的统计信息。你可以指定某个设备(如
-x
: (Extended)- 这是
iostat
最重要、最常用的选项! 它会显示一组扩展的、更详细的 I/O 统计信息,包括await
,svctm
,aqu-sz
,%util
等诊断性能瓶颈的关键指标。强烈建议始终带上-x
参数。
- 这是
-z
: (Zero suppress)- 在报告中省略那些在采样周期内没有任何活动的设备。这可以让输出更简洁,尤其是在系统挂载了大量空闲设备时。
2. 控制输出格式的选项
-t
: (Timestamp)- 在每行输出前打印时间戳。这对于记录和分析长时间的性能数据非常有用。
-y
: (Yes, skip first report)- 禁止打印第一次的统计报告。
iostat
的第一次报告是自系统启动以来的平均值,通常参考意义不大,我们更关心的是实时的、基于采样间隔的瞬时值。使用-y
可以让输出更干净。
- 禁止打印第一次的统计报告。
3. 控制采样方式的参数
[interval]
: 采样间隔(秒)。例如iostat 2
表示每 2 秒刷新一次。[count]
: 采样次数。例如iostat 2 5
表示每 2 秒刷新一次,总共刷新 5 次后退出。如果省略count
,iostat
将会持续运行。
iostat
实例
掌握了参数后,我们来看如何在实际运维中组合使用它们来解决问题。
场景一:快速诊断系统是否存在 I/O 瓶颈
这是最基础也是最核心的用法,用于判断系统变慢是否由磁盘 I/O 引起。
- 问题现象:应用响应缓慢,但
top
显示 CPU 空闲率 (%id
) 很高。 - 诊断命令:
1
2# 每 2 秒刷新一次,显示扩展统计信息和时间戳
iostat -x -t 2 - 分析思路(重点观察以下指标):
%iowait
(CPU 部分):- 如果这个值**持续高于 20%**,说明 CPU 大量时间都在等待 I/O,磁盘是性能瓶颈的重大嫌疑对象。
%util
(设备部分):- 磁盘利用率。如果这个值**持续接近 100%**,表明该磁盘已经饱和,无法处理更多的 I/O 请求,是系统的瓶颈点。
r_await
/w_await
(设备部分):- 读/写请求的平均等待时间(毫秒)。这个值包含了请求在队列中的等待时间和磁盘实际处理请求的时间。
- 经验法则:对于机械硬盘 (HDD),如果
await
时间持续超过 20ms,性能可能已经较差。对于固态硬盘 (SSD),这个值应该远低于 1ms,如果持续超过 5ms 就需要警惕。
aqu-sz
(设备部分):- 平均请求队列长度。如果这个值持续大于 1,说明到达的 I/O 请求速率超过了磁盘的处理能力,请求开始排队。
- 结论:如果同时观察到高
%iowait
、高%util
、高await
和不断增长的aqu-sz
,就可以100% 确定磁盘 I/O 是系统瓶颈。
场景二:分析数据库服务器的读写负载模式
- 问题现象:需要优化一个 MySQL 数据库的性能,首先要了解它的 I/O 模式是读密集型还是写密集型。
- 诊断命令:
1
2# 监控承载数据库文件的磁盘分区(例如 sdb1),以 MB 为单位显示,持续观察
iostat -x -m -p sdb1 1 - 分析思路:
- 比较
rMB/s
和wMB/s
:- 如果
rMB/s
(每秒读 MB 数) 远大于wMB/s
,说明数据库主要是执行查询操作,是读密集型。优化方向可能是增加缓存、优化索引、使用读写分离等。 - 如果
wMB/s
远大于rMB/s
,说明主要是执行插入、更新、删除操作,是写密集型。优化方向可能是优化事务、使用更高性能的 SSD、调整日志写入策略等。
- 如果
- 比较
r/s
和w/s
:- 这两列表示每秒的读写请求次数。结合上面的吞吐量,可以分析 I/O 的大小。例如,如果
wMB/s
很高,但w/s
相对较低,说明应用正在执行大块的顺序写入。反之,如果w/s
很高,但wMB/s
不高,说明是大量的小文件随机写入。
- 这两列表示每秒的读写请求次数。结合上面的吞吐量,可以分析 I/O 的大小。例如,如果
- 比较
场景三:评估新硬件或配置变更的效果
- 问题现象:将数据库从 HDD 迁移到 SSD,或者调整了文件系统挂载参数后,需要量化评估性能提升了多少。
- **诊断方法 (基准测试)**:
- 变更前: 在业务高峰期,使用
iostat -x -t 1 300 > before.log
采集 5 分钟的性能数据。 - 变更后: 在相同的业务高峰期,使用
iostat -x -t 1 300 > after.log
再次采集 5 分钟数据。 - 对比分析:
- 比较两个日志文件中关键指标的平均值和峰值。
- 主要看
r_await
,w_await
,svctm
是否有显著下降。例如,从 HDD 的 10ms 下降到 SSD 的 0.1ms,这就是巨大的性能提升。 - 同时,在相同的负载下,
%util
是否显著降低,aqu-sz
是否不再积压。
- 变更前: 在业务高峰期,使用
场景四:监控并找出“坏邻居”
- 问题现象:在一台虚拟化宿主机或共享存储上,某个虚拟机或应用突然性能下降,怀疑是其他“邻居”的 I/O 操作干扰所致。
- 诊断命令:
1
2# 在宿主机上,显示所有设备及其分区的统计信息,并省略空闲设备
iostat -x -p ALL -z 1 - 分析思路:
- 通过此命令,你可以看到宿主机上所有挂载的逻辑卷或磁盘分区。
- 观察是哪个设备 (
dm-X
,sdX
) 的%util
异常高,并且r/s
或w/s
流量巨大。 - 一旦定位到繁忙的设备,就可以根据虚拟化平台的管理工具或系统配置,反向追查这个设备属于哪个虚拟机,从而找到制造大量 I/O 的“坏邻居”。
运维实战场景
- 判断磁盘瓶颈:观察
%util
、r_await
和w_await
。如果%util
长期高于 80%,且await
时间很长(例如超过 10ms),说明磁盘 I/O 性能已达瓶颈。 - 分析读写模式:通过
r/s
和w/s
的比例,可以判断应用是读密集型还是写密集型。
iostat -x
实际样例 + 分析逻辑:
📌 样例输出
1 | $ iostat -x -p sda 2 3 |
📊 分析逻辑
CPU 部分
%iowait = 8.00
→ CPU 有 8% 的时间在等磁盘,说明 I/O 是瓶颈。%idle = 75.50
→ CPU 其实很空闲,问题不在 CPU。
读写速率
r/s = 200
,rkB/s = 16384
→ 每秒 200 次读请求,总吞吐 16 MB/s。w/s = 150
,wkB/s = 20480
→ 每秒 150 次写请求,总吞吐 20 MB/s。
👉 说明磁盘在同时处理读写操作。
等待时间
r_await = 15.2 ms
→ 平均每个读请求要等 15 毫秒,这偏高(机械盘正常 5~15ms,SSD 应该 <1ms)。w_await = 22.5 ms
→ 写请求平均要等 22 毫秒,也比较慢。
队列和利用率
aqu-sz = 5.5
→ 平均有 5.5 个请求在排队。%util = 98.0
→ 磁盘几乎满负荷工作。
🧭 判断结论
- 这是 I/O 瓶颈,不是 CPU 瓶颈。
- 请求响应时间高、队列长度长、%util 接近 100%,说明磁盘被打满。
- 如果这是 SSD → 性能异常(可能有写放大或固件问题)。
- 如果是 HDD → 属于正常瓶颈,需要增加磁盘或用 SSD。
- 对于数据库类应用,IOPS 和延迟比吞吐量更关键。
🔑 快速判断口诀
看
%util
:<70% → 磁盘比较轻松
70–90% → 磁盘有压力
90% → 磁盘已饱和
看
await
:- HDD 正常几 ms 到十几 ms
- SSD 应该 <1ms,如果 >5ms 就有问题
看
aqu-sz
:- 越大说明队列越长,I/O 堵车
看
%iowait
:- 如果 CPU 大部分时间在等 I/O,说明瓶颈不在 CPU
6. sar
- 全能的系统活动报告器
sar
(System Activity Reporter) 是 Linux 下最全面的性能分析工具之一,它最大的特点是不仅能实时监控,还能收集和报告历史性能数据。
概念与用途
- 作用:全面收集、报告和保存系统的各项活动信息,包括 CPU、内存、I/O、网络、进程等。
- 目的:进行长期性能趋势分析、故障排查和容量规划。
- 核心优势:历史数据分析能力。
sysstat
包会通过定时任务 (cron) 自动收集数据,默认保存在/var/log/sa/
目录下。
基本语法与用法
1 | # 实时监控:每 1 秒采样一次 CPU 使用情况,共 5 次 |
常用监控维度 (选项)
CPU 使用率 (
-u
): 显示%user
,%system
,%iowait
,%idle
等。内存和分页 (
-r
,-B
):-r
: 报告内存利用率 (kbmemfree
,kbmemused
,%memused
)。-B
: 报告分页统计 (pgpgin/s
换入,pgpgout/s
换出)。
块设备 I/O (
-d
):- 报告
tps
(每秒传输次数),rd_sec/s
(每秒读扇区数),wr_sec/s
(每秒写扇区数)。
- 报告
网络统计 (
-n
):sar -n DEV
: 报告网络接口流量 (rxpck/s
收包,txpck/s
发包,rxkB/s
,txkB/s
)。sar
本身 没有直接提供选项来指定单一设备。它会把所有接口的统计都输出。但是可以结合 管道过滤 来只看特定设备,比如:
sar -n DEV 2 5 | grep eth0
sar -n DEV 2 | egrep 'IFACE|eth0|wlan0'
sar -n TCP
: 报告 TCP 连接统计 (active/s
主动连接,passive/s
被动连接)。
进程和上下文切换 (
-w
,-q
):-w
: 报告任务创建 (proc/s
) 和上下文切换 (cswch/s
)。-q
: 报告运行队列长度 (runq-sz
) 和平均负载 (ldavg-1
,ldavg-5
,ldavg-15
)。
sar
常用参数速查
CPU 相关
-u
:CPU 使用率统计(用户、系统、iowait、idle 等)-P ALL
:显示所有 CPU 的使用情况-P <cpu>
:指定某个 CPU
内存
-r
:内存统计(free, used, buffers, cache)-R
:内存页面换入换出(pgpgin/s, pgpgout/s)-B
:分页统计(pgfault/s, pgmajfault/s)-H
:HugePages 使用情况
I/O / 磁盘
-b
:I/O 传输速率统计(tps, rtps, wtps, bread/s, bwrtn/s)-d
:块设备统计(读写次数、吞吐量)-p <dev>
:指定磁盘设备(配合-d
)-q
:队列长度和平均负载-F [MOUNT]
:文件系统统计
网络
-n DEV
:网络接口统计(rxpck/s, txpck/s, rxkB/s, txkB/s 等)-n EDEV
:网络接口错误统计-n TCP
:TCP 协议统计(active/s, passive/s 等)-n ETCP
:TCP 错误统计(retrans/s, orsts/s 等)-n SOCK
:套接字使用情况
电源 / 硬件监控
-m CPU
:CPU 实时主频-m FREQ
:CPU 平均主频-m FAN
:风扇转速-m TEMP
:设备温度-m IN
:电压输入-m USB
:USB 设备
任务 / 进程
-w
:上下文切换和系统调用统计-W
:swap 统计(swapin/s, swapout/s)-q
:运行队列长度、负载统计-f
:显示自开机以来 fork 数-o <file>
:将数据保存到二进制文件
其他
-v
:inode、文件和其他内核表的统计-I SUM
:中断统计(所有 CPU 汇总)-I ALL
:每个中断的详细统计-I <n>
:指定中断号-s [hh:mm:ss]
:开始时间-e [hh:mm:ss]
:结束时间-i <sec>
:间隔时间-h
:更友好格式显示大数值
⚡ 使用模式示例:
- 实时采样:
sar -u 2 5
→ 每 2 秒刷新一次,共采集 5 次 CPU 使用率 - 历史数据:
sar -r -f /var/log/sa/sa10
→ 查看第 10 天的内存历史数据
要不要我帮你把这些参数再整理成 不同场景下的常用组合命令(比如排查 CPU 瓶颈、I/O 瓶颈、网络瓶颈的常见 sar 用法)?
运维场景
- 排查夜间性能问题:服务器在凌晨 3 点变慢,但白天无法复现。运维人员可以通过
sar -u -f /var/log/sa/sa<日期>
来查看当时 CPU 的%iowait
是否异常升高,从而定位问题。 - 容量规划:通过分析过去一个月的
sar
网络流量数据 (-n DEV
),可以预测未来的带宽需求。
sar
最强大的地方在于其历史数据追溯能力,这使它成为事后故障分析、性能趋势预测和容量规划的无价之宝。
sysstat
包默认会通过 cron 或 systemd timer 每 10 分钟对系统进行一次快照采样,并将数据以二进制格式保存在 /var/log/sa/
目录下,文件名通常是 saDD
(DD
代表日期,如 sa17
代表 17 号的数据)。还有一个人类可读的文本汇总报告 sarDD
。
sar
实例
场景一:事后故障分析 - “服务器昨天半夜为什么那么卡?”
这是 sar
最经典的用途。白天无法复现的问题,可以通过回溯历史日志来定位。
问题现象:用户报告昨晚(假设是 16 号)凌晨 2 点到 3 点之间,应用访问极度缓慢,但现在已经恢复正常。
诊断步骤:
第一步:检查总体负载和 CPU
- 命令:
1
2
3
4# -q: 查看负载和队列长度
# -f: 指定历史日志文件
# -s, -e: 指定开始和结束时间
sar -q -f /var/log/sa/sa16 -s 02:00:00 -e 03:00:00 - 分析:查看
ldavg-1
(1分钟负载) 在该时间段是否远超 CPU 核心数。如果负载很高,再看是 CPU 还是 I/O 问题。1
2# -u: 查看 CPU 使用情况
sar -u -f /var/log/sa/sa16 -s 02:00:00 -e 03:00:00 - 分析:
- 如果
%user
或%system
很高,说明是 CPU 密集型任务,可能是某个定时脚本或批处理任务触发了。 - 如果
%iowait
很高,说明瓶颈在 I/O,CPU 在等待磁盘。
- 如果
- 命令:
第二步:深入分析 I/O 瓶颈 (如果上一步发现
%iowait
高)- 命令:
1
2
3# -d: 查看磁盘活动
# -p: 美化设备名,更易读
sar -d -p -f /var/log/sa/sa16 -s 02:00:00 -e 03:00:00 - 分析:查看哪个设备 (
DEV
) 的%util
在该时段接近 100%,并且await
(平均等待时间) 异常高。这通常是由夜间的备份任务、数据同步或日志归档引起的。
- 命令:
第三步:检查内存和交换活动
- 命令:
1
2
3# -r: 查看内存使用
# -S: 查看交换空间使用
sar -rS -f /var/log/sa/sa16 -s 02:00:00 -e 03:00:00 - 分析:查看
%memused
是否接近 100%,以及kbswpout/s
(换出到 swap 的速率) 是否有非零值。如果发现有大量的交换活动,说明当时物理内存被耗尽,可能是某个内存泄漏的应用或计划任务导致的。
- 命令:
结论:通过这一系列的回溯查询,即使问题已经消失,运维人员也能准确定位故障根源是 CPU 密集任务、磁盘 I/O 瓶颈还是内存耗尽,从而进行针对性的优化。
场景二:性能趋势分析与容量规划
sar
记录的长期数据是进行容量规划的宝贵财富。
问题现象:业务量持续增长,需要评估当前服务器资源(CPU、内存、网络)何时会达到瓶颈,以便提前采购和扩容。
诊断步骤:
分析 CPU 使用率的长期趋势
- 目标:找出业务高峰期(例如工作日下午 2 点到 4 点)的 CPU 平均使用率,并观察其月度变化。
- 脚本示例 (分析过去一周的数据):
1
2
3
4
5
6for day in $(seq -w $(date -d "7 days ago" +%d) $(date +%d)); do
echo "--- Analyzing CPU for day ${day} ---"
sar -u -f /var/log/sa/sa${day} -s 14:00:00 -e 16:00:00 | \
grep 'Average:' | \
awk '{print "Avg %user:", $3, "Avg %system:", $5, "Avg %idle:", $8}'
done - 分析:将每天高峰期的 CPU 使用率(特别是
%idle
的反面)记录下来,制作成图表。如果发现空闲率 (%idle
) 逐周稳定下降,例如从 40% -> 30% -> 20%,就可以预测出大约在几周后 CPU 资源将耗尽。
分析网络带宽使用情况
- 目标:评估当前网络出口带宽是否足够。
- 命令:
1
2
3
4
5
6
7# -n DEV: 查看网络接口流量
# 分析过去一个月所有日期的 sar 日志
find /var/log/sa/ -name 'sa*' -mtime -30 -exec sar -n DEV -f {} + | \
grep 'Average:' | \
grep 'eth0' | \
awk '{print "rxkB/s:", $5, "txkB/s:", $6}' | \
sort -k4 -nr | head -n 5 - 分析:这个命令会找出过去 30 天内,
eth0
网卡在业务高峰期平均发送流量 (txkB/s
) 最高的 5 个记录。通过这些峰值数据,你可以判断当前带宽利用率是否已经接近签约带宽的 80%,从而决定是否需要升级带宽。
场景三:健康巡检与基线建立
为服务器建立性能基线,是快速发现异常的前提。
- 问题现象:如何判断服务器当前的性能表现是“正常”还是“异常”?
- 方法:
- 建立基线: 在系统运行平稳、业务正常的时期,收集一周的
sar
数据作为基线。1
2
3
4# 汇总过去 7 天每天的 CPU 平均使用情况
sar -u -f $(ls /var/log/sa/sa* | tail -n 7) | grep 'Average:'
# 汇总过去 7 天每天的磁盘平均 I/O 情况
sar -d -p -f $(ls /var/log/sa/sa* | tail -n 7) | grep 'Average:' - 日常巡检: 编写一个脚本,每天自动运行
sar
获取前一天的性能摘要,并与已建立的基线进行对比。1
2
3
4
5
6
7
8
9# 获取昨天的 CPU %iowait 平均值
yesterday_iowait=$(sar -u -f /var/log/sa/sa$(date -d "1 day ago" +%d) | grep 'Average:' | awk '{print $6}')
# 假设基线 iowait 不应超过 5.0
baseline_iowait=5.0
if (( $(echo "$yesterday_iowait > $baseline_iowait" | bc -l) )); then
echo "Warning: Yesterday's average iowait (${yesterday_iowait}%) is above baseline (${baseline_iowait}%)!"
fi
- 建立基线: 在系统运行平稳、业务正常的时期,收集一周的
- 结论:通过建立性能基线,任何偏离正常范围的指标都会被快速识别出来,实现了从“被动救火”到“主动预防”的转变。
sar
的精髓在于它赋予了运维人员“时间旅行”的能力,能够将瞬时的性能问题放在一个长期的时间维度里去审视,从而发现问题的根本原因和未来趋势。
7. pidstat
- 进程级性能监控利器
pidstat
专注于监控单个进程或线程的资源使用情况,是 top
和 ps
的强大补充。
概念与用途
- 作用:实时、详细地显示指定进程或所有进程的 CPU、内存、I/O、上下文切换等资源使用情况。
- 目的:精确定位是哪个进程或线程导致了系统资源消耗过高。
基本语法与用法
1 | # 每 2 秒监控一次所有进程的 CPU 使用情况 |
核心监控维度 (选项)
- CPU (
-u
):%usr
: 进程在用户空间消耗的 CPU 百分比。%system
: 进程在内核空间消耗的 CPU 百分比。%CPU
: 进程总的 CPU 使用率。
- 内存 (
-r
):minflt/s
: 每秒次要缺页错误次数 (不涉及磁盘 I/O)。majflt/s
: 每秒主要缺页错误次数 (需要从磁盘加载内存页)。该值过高表示内存压力大。VSZ
: 虚拟内存大小 (KB)。RSS
: 常驻内存大小 (KB),即进程实际占用的物理内存。持续增长可能意味着内存泄漏。
- 磁盘 I/O (
-d
):kB_rd/s
: 进程每秒从磁盘读取的数据量。kB_wr/s
: 进程每秒向磁盘写入的数据量。kB_ccwr/s
: 进程取消的写操作数据量。
- 上下文切换 (
-w
):cswch/s
: 每秒自愿上下文切换次数 (如等待资源)。nvcswch/s
: 每秒非自愿上下文切换次数 (如时间片用完被强制调度)。该值过高说明 CPU 竞争激烈。
- 线程级监控 (
-t
):- 此选项会额外显示每个线程 (TID/LWP) 的统计信息,对于分析多线程应用(如 Java)非常有用。
- 指定进程 (
-p <PID>
):pidstat -p 1234 -urd 1
:每秒监控 PID 为 1234 的进程的 CPU、内存和 I/O。
运维实战场景
- 定位高 CPU 消耗的 Java 线程:
- 用
top -H -p <java_pid>
找到消耗 CPU 最高的线程 ID (LWP)。 - 用
pidstat -t -p <java_pid> -u 1
确认该 LWP 的 CPU 占用。 - 将 LWP 转换为十六进制,并使用
jstack
打印 Java 堆栈,找到对应的 Java 线程,从而定位到问题代码。
- 用
- 找出疯狂写日志的进程:
- 运行
pidstat -d 1
,观察哪个进程的kB_wr/s
异常高。
- 运行
好的,我们来系统地拆解 pidstat
命令。这是一个非常精细化的工具,能将性能监控的粒度从整个系统下沉到具体的进程和线程,是精准定位资源消耗“元凶”的利器。
pidstat
命令详解
pidstat
是 sysstat
工具集的一员,专注于按进程提供详细的资源使用报告。
基本语法: pidstat [选项] [间隔秒数] [次数]
1. 核心功能选项 (按监控维度分类)
这些选项决定了 pidstat
监控哪一类资源,它们可以组合使用。
-u
: (CPU) - 默认选项- 报告进程的 CPU 使用统计。
- 关键列:
%usr
: 进程在用户空间(执行应用程序代码)消耗的 CPU 百分比。%system
: 进程在内核空间(执行系统调用)消耗的 CPU 百分比。%guest
: 进程在虚拟机中运行 guest 代码的 CPU 百分比。%CPU
: 进程总的 CPU 使用率。注意:在多核系统上,这个值可以超过 100%。例如,250% 表示该进程用满了 2.5 个 CPU核心。
-r
: (Memory / Page Faults)- 报告进程的内存使用和缺页错误统计。
- 关键列:
minflt/s
: 每秒次要缺页错误 (minor fault)。这意味着进程需要的内存在物理内存中,但需要内核为其建立页表映射。这个值较高通常是正常的。majflt/s
: 每秒主要缺页错误 (major fault)。这意味着进程需要的内存页已经不在物理内存中(可能被换出到磁盘了),需要从磁盘重新加载。这个值持续不为零,是内存压力大的明确信号。VSZ
: 虚拟内存大小 (Virtual Size),单位 KB。RSS
: 常驻内存大小 (Resident Set Size),单位 KB。这是进程当前实际占用的物理内存大小。如果一个进程的 RSS 持续增长而不下降,可能存在内存泄漏。
-d
: (Disk I/O)- 报告进程的磁盘 I/O 统计。
- 关键列:
kB_rd/s
: 进程每秒从磁盘读取的数据量 (KB)。kB_wr/s
: 进程每秒向磁盘写入的数据量 (KB)。kB_ccwr/s
: 进程取消的写操作数据量 (KB)。当进程向页缓存写入,但随后又截断文件时会发生。- 注意:这个统计只包括真正的磁盘 I/O,不包括通过文件系统缓存的读写。
-w
: (Context Switches)- 报告进程的上下文切换统计。
- 关键列:
cswch/s
: 每秒自愿上下文切换 (voluntary context switches)。通常发生在进程因为等待资源(如 I/O、锁)而主动放弃 CPU 时。nvcswch/s
: 每秒非自愿上下文切换 (non-voluntary context switches)。发生在进程的 CPU 时间片用完,被操作系统调度器强制剥夺 CPU 时。这个值持续很高,说明 CPU 竞争非常激烈。
-t
: (Threads)- 这是一个增强选项,可以与其他功能选项(如
-u
,-r
)配合使用。它会显示进程下的所有线程的统计信息,而不仅仅是主进程。 - 关键列:
TGID
: 主进程的 ID (Thread Group ID)。TID/LWP
: 线程的真实 ID (Light Weight Process)。
- 这是一个增强选项,可以与其他功能选项(如
2. 控制输出对象的选项
-p <PID> | ALL
: (Process ID)- 指定要监控的进程 ID。你可以用逗号分隔多个 PID (如
-p 1234,5678
)。 - 使用
ALL
关键字表示监控所有当前活动的进程。
- 指定要监控的进程 ID。你可以用逗号分隔多个 PID (如
-C <command_string>
: (Command)- 监控命令名中包含指定字符串的进程。例如
-C java
会监控所有包含 “java” 字符串的进程。
- 监控命令名中包含指定字符串的进程。例如
-U <user_name>
: (User)- 只监控指定用户拥有的进程。
3. 控制输出格式的选项
-h
: (Human-readable / Horizontal)- 在一个易于阅读的水平格式中显示所有统计信息,而不是默认的多行格式。
-I
: (I/O class)- 在
-d
模式下,显示 I/O 优先级(如果有的话)。
- 在
-l
: (Long format)- 显示更长的进程名或命令行。
pidstat
实例
pidstat
的威力在于组合使用这些选项,进行精准打击。
场景一:找出哪个进程在“吃”CPU
- 问题现象:
top
或uptime
显示系统 CPU 使用率很高。 - 诊断命令:
1
2
3
4
5# 每 2 秒执行一次 "pidstat -u | sort -k8 -nr | head -n 20"
watch -n 2 "pidstat -u | sort -k9 -nr | head -n 20"
# 每 2 秒执行一次 "pidstat -u 1 1" (采样间隔1秒, 次数1次)
watch -n 2 "pidstat -u 1 1 | tail -n +4 | sort -k9 -nr | head -n 20" - 分析思路:
- 这个命令会动态地将 CPU 占用最高的进程排在最前面。
- 观察
%CPU
列,如果某个进程持续占用一个或多个核心(例如nginx
占用 400%),就找到了元凶。 - 同时观察
%usr
和%system
的比例。如果%usr
高,是应用逻辑问题;如果%system
高,是系统调用(如频繁 I/O)问题。
场景二:定位 Java 应用中高 CPU 占用的具体线程
这是 pidstat
最经典的“杀手级”应用之一。
- 问题现象:一个 Java 服务进程 CPU 占用 100% 或更高,需要定位到是哪段代码出了问题。
- 诊断步骤:
- 找到 Java 进程的 PID:
pgrep java
- 用
pidstat
监控该进程的所有线程:1
2# 假设 Java 进程 PID 是 1234
pidstat -u -p 1234 -t 1 - 找出 CPU 最高的线程 ID (TID/LWP): 在输出中,找到
%CPU
最高的那个线程,记下它的TID
列的值,例如1255
。 - 将 TID 转换为十六进制:
1
2printf "%x\n" 1255
# 输出: 4e7 - 使用
jstack
打印 Java 堆栈并查找该线程:1
jstack 1234 | grep '0x4e7' -A 30
- 找到 Java 进程的 PID:
- 结论:
jstack
的输出会精确地告诉你这个nid=0x4e7
的线程当前正在执行哪一个 Java 类、哪一个方法。至此,问题代码就完全暴露了。
场景三:诊断“磁盘很忙,但不知道是谁干的”
- 问题现象:
iostat
显示sda
磁盘的%util
接近 100%,但需要知道是哪个进程导致的。 - 诊断命令:或者使用
1
2# 每 2 秒刷新一次,显示所有进程的 I/O 情况
pidstat -d 2iotop
的替代方案:1
2# 持续监控,按写入速率排序
pidstat -d 1 | sort -k5 -nr - 分析思路:
- 观察
kB_rd/s
和kB_wr/s
列。哪个进程的这两列数值最大,就是 I/O 压力的制造者。 - 这对于找出正在疯狂写日志的应用、正在进行大量数据读写的数据库,或者失控的备份脚本非常有效。
- 观察
场景四:分析是否存在内存泄漏
- 问题现象:一个长期运行的服务,其内存占用似乎在不断缓慢增长。
- 诊断命令:
1
2# 每 30 秒采样一次,持续监控指定进程的内存使用
pidstat -r -p <PID> 30 - 分析思路:
- 将输出重定向到一个文件,长时间观察
RSS
(实际物理内存) 列的变化趋势。 - 如果
RSS
的值在没有业务高峰的情况下,呈现出“只增不减”或“阶梯式增长且从不回落”的趋势,那么该进程有很高的内存泄漏嫌疑。 - 同时,如果
majflt/s
(主要缺页错误) 偶尔出现,也佐证了物理内存可能不足,部分内存被换出。
- 将输出重定向到一个文件,长时间观察
pidstat
就像一个手术刀,能帮助运维工程师在复杂的系统中,精确地剖析出每一个进程的资源消耗细节,是从系统级监控走向应用级诊断的关键桥梁。
8. perf
- 终极性能分析神器
perf
常用子命令:
perf stat:收集整体性能计数器(CPU cycles, instructions, cache-misses 等)
perf record:采样收集事件信息,生成 perf.data
文件
perf report:分析 perf.data
文件,展示热点函数
perf top:实时显示性能热点(类似 top
)
perf trace:跟踪系统调用(类似 strace
,但更高效)
perf list:显示所有可用的事件
perf sched:调度器相关分析(perf sched latency
, perf sched map
等)
perf annotate:展示函数源码级别的热点
perf mem:内存访问分析(load/store latency 等)
perf
是 Linux 内核自带的性能分析工具,功能极其强大,能够深入到硬件、内核和应用程序函数级别进行分析。
概念与用途
- 作用:通过采样 CPU 的性能监控单元 (PMU, Performance Monitoring Unit) 和内核事件 (tracepoints),分析程序和系统的性能瓶颈。
- 目的:定位到消耗 CPU 的具体函数、分析缓存命中率、分支预测失败率等底层硬件事件。常用于生成**火焰图 (Flame Graphs)**。
核心子命令
perf
通过子命令来执行不同任务:
perf list
: 列出当前系统支持的所有可测量事件。perf stat
: 运行一个命令,并统计其运行期间的性能数据摘要。1
2perf stat ls
# 输出包括指令数、时钟周期、IPC (每周期指令数)、缓存未命中等。perf top
: 类似于top
,但实时显示消耗 CPU 最多的函数(包括内核函数和用户函数)。这是快速定位热点函数的利器。1
sudo perf top
perf record
: 采样并记录性能数据,生成一个perf.data
文件,用于后续分析。1
2# 对整个系统进行采样,频率为 99Hz,并记录调用栈
sudo perf record -F 99 -a -g -- sleep 10perf report
: 读取并分析perf.data
文件,以交互式界面的形式展示函数的热点分布。
火焰图生成流程
火焰图是可视化性能瓶颈的强大工具。
- 采集数据:
perf record -F 99 -p <PID> -g -- sleep 30
- 生成脚本输入:
perf script > out.perf
- 折叠堆栈:
stackcollapse-perf.pl out.perf > out.folded
(需要从 FlameGraph 项目获取脚本) - 生成 SVG 图片:
flamegraph.pl out.folded > kernel.svg
- 在浏览器中打开
kernel.svg
,图中宽度越宽的函数,表示它消耗的 CPU 时间越多。
总结
perf
是高级性能工程师和内核开发者的必备工具,它提供了其他工具无法比拟的深度和广度,是解决复杂性能问题的最终手段。
perf
,这无疑是 Linux 性能分析工具箱中的“核武器”。它非常强大,但也相对复杂。
perf
- Linux 性能事件分析神器
一、perf
概念
- 全称:Performance Events for Linux
- 作用:
perf
不是一个单一的工具,而是一个工具集。它利用 Linux 内核的perf_events
子系统,能够访问 CPU 的性能监控单元 (PMU, Performance Monitoring Unit) 和内核中的**跟踪点 (tracepoints)**,从而对软件和硬件的性能进行极其深入的分析。 - 分析层次:
- 硬件层面:CPU 周期、指令数、缓存未命中 (Cache Misses)、分支预测失败 (Branch Misses) 等。这些是衡量 CPU 执行效率的底层指标。
- 内核层面:系统调用、上下文切换、缺页中断、调度器事件等。
- 应用层面:找出用户态应用程序中消耗 CPU 最多的热点函数。
- 核心优势:
- 内核集成:作为内核的一部分,开销较低,数据更精确。
- 全景视图:能够同时分析用户代码和内核代码的性能,打通应用和系统之间的壁垒。
- 事件驱动:可以基于非常丰富的性能事件进行采样。
- 火焰图 (Flame Graph) 的主要数据来源。
二、安装 perf
perf
通常不随系统默认安装,需要根据你的内核版本来安装对应的工具包。
- 对于 Debian/Ubuntu 系统:
1
2
3# $(uname -r) 会自动获取当前的内核版本号
sudo apt update
sudo apt install linux-tools-common linux-tools-$(uname -r) - 对于 RHEL/CentOS 系统:
1
sudo yum install perf
- 验证安装:
1
perf --version
三、perf
核心子命令与用法
perf
的功能是通过一系列子命令来实现的。
1. perf list
- 查看可用的性能事件
在开始分析之前,先了解你的系统支持哪些事件。
- 用法:
1
perf list
- 输出解读:
- Hardware Event: PMU 提供的硬件事件,如
cycles
,instructions
,cache-misses
。 - Software Event: 内核提供的软件事件,如
context-switches
,page-faults
。 - Tracepoint Event: 内核代码中预设的跟踪点,覆盖了系统调用的进入/退出、调度器的决策、网络包的收发等海量细节。例如
syscalls:sys_enter_openat
。
- Hardware Event: PMU 提供的硬件事件,如
2. perf stat
- 性能数据“体检”
对一个命令(或整个系统)进行一次快速的性能统计,给出摘要报告。
- 用法:
- 分析单个命令:
1
2# 运行 `ls -R /` 命令,并统计其性能数据
perf stat ls -R / >/dev/null - 监控正在运行的进程:
1
2# 监控 PID 为 1234 的进程,持续 5 秒
perf stat -p 1234 sleep 5 - 监控整个系统:
1
2# 监控整个系统 5 秒
sudo perf stat -a sleep 5
- 分析单个命令:
- 关键输出指标:
task-clock (msec)
: 任务实际占用的 CPU 时间。context-switches
: 上下文切换次数。cycles
: 消耗的 CPU 时钟周期数。instructions
: 执行的指令数。IPC (instructions per cycle)
: 非常重要的指标! 每个 CPU 周期执行的指令数。值越高,说明 CPU 的流水线效率越高,程序对 CPU 的利用越好。如果 IPC 很低(例如 < 1.0),可能意味着大量的缓存未命中或分支预测失败,导致 CPU 频繁等待。cache-misses
: 缓存未命中次数。branch-misses
: 分支预测失败次数。
3. perf top
- 实时热点函数分析器
类似 top
,但它显示的是当前消耗 CPU 最多的函数,而不是进程。
- 用法:
1
2# 需要 root 权限来分析整个系统
sudo perf top - 交互界面:
- Overhead: 函数消耗 CPU 时间的百分比。
- Symbol: 函数名。
- Shared Object: 函数所在的库或可执行文件(例如
[kernel.kallsyms]
表示内核函数)。
- 常用选项:
-p <PID>
: 只分析指定进程。-e <event>
: 按指定事件(如cache-misses
)来排序,找出缓存未命中率最高的函数。
4. perf record
& perf report
- 离线深度分析
这是 perf
最强大的用法,用于采样、记录,然后进行详细的离线分析。
工作流程:
perf record
(记录): 对目标进行性能事件采样,并将结果保存到perf.data
文件中。perf report
(报告): 读取perf.data
文件,以交互式的方式展示热点分析结果。
用法示例:
1
2
3
4
5
6
7
8# 1. 记录系统范围的 CPU 采样数据 10 秒钟
# -F 99: 采样频率为 99Hz (每秒 99 次)
# -a: System-wide,监控所有 CPU
# -g: 记录函数的调用图 (call graph),对分析函数调用关系至关重要
sudo perf record -F 99 -a -g -- sleep 10
# 2. 分析生成的 perf.data 文件
perf reportperf report
交互界面:- 主界面按百分比显示热点函数。
- 选中一个函数按回车,可以展开其调用栈,看到是谁调用了它 (callers) 以及它调用了谁 (callees)。
- 按
a
可以在函数和源码级别之间切换(需要调试符号)。
perf
实战应用场景
场景一:快速定位导致 CPU 100% 的“元凶”函数
- 问题现象:
top
显示某个应用进程 CPU 占用率持续 100%。 - 诊断步骤:
找到进程 PID:
pgrep my_app
(假设 PID 为 2345)。实时定位热点:
1
sudo perf top -p 2345
- 在
perf top
的输出中,排在第一行的函数就是当前最消耗 CPU 的函数。这通常能直接定位到问题代码(比如一个死循环或一个计算密集的算法)。
- 在
如果问题复杂,进行离线分析:
1
2
3
4
5# 对该进程进行 15 秒的调用图采样
sudo perf record -p 2345 -g -- sleep 15
# 分析报告
perf report- 在
perf report
中,你可以详细地追溯调用链,理解为什么这个热点函数会被如此频繁地调用。
- 在
场景二:生成火焰图,可视化性能瓶颈
火焰图是分析 CPU 性能的终极利器,而 perf
是其主要的数据来源。
- 问题现象:需要直观地向开发人员展示复杂应用的性能瓶颈所在。
- 操作流程:
- 安装火焰图工具:
1
2git clone https://github.com/brendangregg/FlameGraph.git
cd FlameGraph - 使用
perf record
采集数据 (必须带-g
):1
sudo perf record -F 99 -a -g -- sleep 30
- 生成火焰图:
1
2
3
4
5
6# 将 perf.data 转换为可读的堆栈信息
sudo perf script > out.perf
# 使用火焰图工具的脚本进行折叠和绘图
./stackcollapse-perf.pl ../out.perf > ../out.folded
./flamegraph.pl ../out.folded > ../myserver.svg
- 安装火焰图工具:
- 结果分析:
- 用浏览器打开生成的
myserver.svg
文件。 - 火焰图的横轴代表 CPU 占用时间,“平顶”越宽的函数,就意味着它本身消耗了越多的 CPU 时间,是直接的性能瓶颈。
- 火焰图的纵轴代表函数调用栈的深度。
- 这是一个极其直观的工具,能让复杂的性能问题一目了然。
- 用浏览器打开生成的
场景三:分析程序为何运行缓慢 (IPC 过低)
- 问题现象:程序运行缓慢,但 CPU 使用率并未跑满,怀疑是内存访问或分支预测效率低下。
- 诊断步骤:
使用
perf stat
进行“体检”:1
perf stat -e cycles,instructions,cache-misses,branch-misses ./my_slow_program
分析指标:
- 计算 IPC: 用
instructions
除以cycles
。如果 IPC 值非常低(例如 < 0.5),说明 CPU 大部分时间都在等待,而不是在执行指令。 - 分析原因: 查看
cache-misses
和branch-misses
的比例。- 如果缓存未命中率高,说明程序的数据访问模式不友好,导致频繁从慢速的主存中读取数据。优化方向是改善数据局部性(Data Locality)。
- 如果分支预测失败率高,说明代码中存在大量难以预测的条件分支(if/else, switch),打乱了 CPU 的指令流水线。优化方向是重构代码逻辑,减少分支。
- 计算 IPC: 用
perf
是一个专业且深入的工具,初次接触可能会觉得复杂。建议从 perf stat
和 perf top
开始,熟练后再深入使用 perf record
和火焰图,它将成为你解决性能问题的最强有力的武器。
服务器性能评估的思路与步骤
掌握工具只是第一步,更重要的是形成一套行之有效的方法论。我将它总结为**”三步走”**策略,它能帮你从纷繁复杂的数据中找出问题的根源。
第一步:宏观概览(Broad View)
目标:快速判断问题出在哪个子系统,是 CPU、内存、磁盘还是网络。
- 观察系统平均负载(
top
或uptime
):负载值是否高于 CPU 核心数?如果高于,说明系统有大量的任务在排队等待执行。 - 检查 CPU 状态(
vmstat
):- 高
r
值:CPU 密集型任务过多。 - 高
wa
值:I/O 密集型任务过多,需要排查磁盘或网络。
- 高
- 检查内存状态(
vmstat
或free
):- 高
si
/so
值:内存不足,正在频繁使用交换区。
- 高
- 检查网络状态(
netstat
或ss
):是否有大量的网络连接处于异常状态?
结论:通过这一步,你应该能得到一个初步的结论:比如,“这台服务器的瓶颈似乎在 I/O”或者“问题出在 CPU 资源不足”。
第二步:聚焦排查(Drill Down)
目标:在确定了问题子系统后,精确找到是哪个进程、哪个设备或哪个网络连接导致了问题。
- CPU 问题:使用
top
或htop
,按 CPU 使用率排序(%CPU
),找出是哪个进程消耗了最多的 CPU 资源。然后可以继续用strace
等工具来跟踪该进程的系统调用。 - I/O 问题:
- 磁盘:使用
iostat -x
,找出%util
接近 100% 的磁盘。 - 网络:使用
netstat
或ss
,结合tcpdump
等抓包工具,分析网络流量和连接状态。
- 磁盘:使用
- 内存问题:使用
top
找到内存占用最高的进程。如果进程占用内存合理,但整体内存不足,可能需要增加物理内存或优化应用程序配置。
结论:这一步让你从“系统有瓶颈”的模糊概念,转变为“**Nginx 进程占用了 80% 的 CPU,并且 /dev/sdb
磁盘的使用率达到了 98%**”这样的具体问题。
第三步:解决与验证(Solve & Verify)
目标:针对发现的具体问题,采取行动并验证效果。
- 解决:
- CPU 瓶颈:优化代码,增加服务器核心,或调整负载均衡。
- I/O 瓶颈:优化数据库索引,升级到 SSD,或增加磁盘阵列。
- 内存瓶颈:增加内存,优化应用程序内存配置,或配置缓存。
- 验证:在采取措施后,重新使用第一步和第二步的工具进行观察。如果
vmstat
的r
值降下来了,或者iostat
的%util
下降了,那么你的优化就起作用了。
这套方法论就像医生看病一样:先问诊(宏观概览),再做检查(聚焦排查),最后开药(解决与验证)。它能确保你不会盲目地修改配置,而是基于数据做出理性的决策。
现在,你是否对这套思路有了更清晰的了解?或者,你有没有在工作中遇到过某个具体的性能问题,我们可以一起按照这套思路来分析一下?