译者注:原文 Linux Performance Analysis in 60,000 Milliseconds,译者对文章中部分内容做了删减或补充。有些代码块显示效果不佳,这是因为命令行输出时使用制表符和空格做了对齐处理,可以复制到文本编辑器中查看。
虽然这是 2015 年的文章,考虑到生产环境并没有进化到大规模使用现在流行的那些神奇小玩意儿,因此还是适用的。
文中部分命令来自
sysstat
工具包,主流发行版都可以通过包管理器安装。你还需要使用systemctl enable --now sysstat
启动相关的服务以便工具开始记录数据。
登录一台存在性能问题的 Linux 服务器,你会在头一分钟里检查什么?
在 Netflix 我们有一个庞大的 EC2 Linux 云,有数不清的工具在做监控和分析。Altas 面向整个云,而 Vector 专注于特定实例。虽然大部分问题都可以用这些工具解决,有时候还是需要登录机器运行一些标准的 Linux 性能分析工具。
概述
Netflix Performance Engineering 团队将向你展示如何在 60 秒内使用标准的命令行工具对系统进行调查分析,通过这 10 条命令可以大致掌握系统的使用情况。
uptime
dmesg | tail
vmstat 1
mpstat -P ALL 1
pidstat 1
iostat -xz 1
free -m
sar -n DEV 1
sar -n TCP,ETCP 1
top
这些命令的输出基本可以覆盖 The USE Method 方法论的要求,并且交叉检查还可以排除一些嫌疑项,缩小分析范围。
要获取有关这些工具的更多信息,请使用 man <cmd>
。
1. uptime
$ uptime
23:51:26 up 21:31, 1 user, load average: 30.02, 26.43, 19.02
该命令的的输出结果可以解读为
- 当前时间
23:51:26
- 系统自上次启动以来运行了 21 小时 31 分钟
- 当前有 1 个用户登录
- 系统在过去 1、5、15 分钟的平均负载
该命令的输出非常笼统,因此只适合获取大致概念,如果你发现 1 分钟的平均负载比 15 分钟的平均负载低得多,那么极有可能已经错过了问题。
uptime
也是 w
输出的第一行内容。
2. dmesg | tail
$ dmesg | tail
[ 8.628757] systemd-journald[686]: Received client request to flush runtime journal.
[ 9.749679] input: PC Speaker as /devices/platform/pcspkr/input/input6
[ 9.849915] RAPL PMU: API unit is 2^-32 Joules, 0 fixed counters, 10737418240 ms ovfl timer
[ 9.851236] Free page reporting enabled
[ 9.924601] piix4_smbus 0000:00:01.3: SMBus Host Controller at 0x700, revision 0
[ 10.725630] XFS (sda1): Mounting V5 Filesystem
[ 10.726238] XFS (dm-2): Mounting V5 Filesystem
[ 10.850352] XFS (sda1): Ending clean mount
[ 11.136524] XFS (dm-2): Ending clean mount
[ 7135.242114] systemd-rc-local-generator[1943]: /etc/rc.d/rc.local is not marked executable, skipping.
展示最近 10 条系统信息,看看有没有 Out of memory: Kill process ***
或者 TCP: Possible SYN flooding on port ***. Dropping request. Check SNMP counters.
这样的字眼。
3. vmstat 1
虽然这个命令名叫 virtual memory stat,它也可以向控制台输出进程、内存、I/O 等资源整体运行状态。这里的采样 / 输出间隔是 1 秒。
$ vmstat 1
procs ---------memory---------- ---swap-- -----io---- -system--- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 200889792 73708 591828 0 0 0 5 6 10 96 1 3 0 0
0 0 200889920 73708 591860 0 0 0 592 13284 4282 98 1 1 0 0
0 0 200890112 73708 591860 0 0 0 0 9501 2154 99 1 0 0 0
0 0 200889568 73712 591856 0 0 0 48 11900 2459 99 0 0 0 0
0 0 200890208 73712 591860 0 0 0 0 15898 4840 98 1 1 0 0
^C
procs
进程r
:在 CPU 上运行并等待轮转的进程数量,大于 CPU 数量表示资源饱和,可能需要考虑增加 CPU
memory
内存,以 kB 为单位swpd
:使用的虚拟内存大小,如果swpd
的值不为 0,但是swap
里的si
,so
长期是 0,那也是 OK 的free
:空闲的物理内存,如果是个很大的数字就不用担心;如果数字不大,但是swap
里的si
,so
长期是 0,那也不用担心cache
用作缓存的内存大小,cache
值很大且io
里的bi
很小说明频繁访问的文件基本都被缓存了
swap
磁盘交换区si
和so
分别表示 每秒从磁盘交换区到内存的读写,如果这两个值不为 0,说明内存不太够了
io
- 随机磁盘读写的时候,
bi
和bo
越大,CPU 在 I/O 上等待的时间越长
- 随机磁盘读写的时候,
system
in
和cs
分别表示每秒的中断数和上下文切换次数,也可以体现 CPU 的等待时间
cpu
us(user time)
:用户进程执行时间占比sy(system time (kernel))
:内核系统进程执行时间占比id(idle)
:闲置时间占比wa(wait I/O)
:I/O 等待时间占比
本例中 cpu-us
基本在 95% 以上,然而 process-r
显示 CPU 资源饱和度并不高,因此没什么问题。
cpu-sy
是处理 I/O 等操作必需的,这个值超过 20% 暗示内核处理 I/O 的效率可能不高。
4. mpstat -P ALL 1
mpstat
表示 Multiprocessor Statistics,报告与 CPU 有关的统计信息。-P ALL
表示监控所有 CPU,也可以通过编号单独指定某个 CPU。本例中采样间隔是 1 秒。
由于 mpstat
关注单个处理器的状态,可以发现一些负载不均衡的情况。例如有个单线程应用吃满了一个处理器,而其他处理器处于闲置状态,这种情况无法通过查看处理器平均占用识别。
5. pidstat 1
pidstat
可以监控全部或指定进程的 CPU、内存、线程、设备 I/O 等资源的占用情况。首次运行时显示自系统启动开始的各项统计信息,之后运行将显示自上次运行该命令以来的统计信息,也可以按照一定采样间隔和次数执行。
pidstat [ 选项 ] [ <时间间隔> [ <计数> ] ] [ -e <程序> <参数> ]
u
:默认,显示各进程的 CPU 使用情况r
:显示各进程的内存使用情况d
:显示各进程的 I/O 使用情况w
:显示各进程的上下文切换情况t
:统计数据精确到线程p
:指定进程号,ALL
表示所有进程
6. iostat -xz 1
$ iostat -xz 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
73.96 0.00 3.73 0.03 0.06 22.21
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
xvda 0.00 0.23 0.21 0.18 4.52 2.08 34.37 0.00 9.98 13.80 5.42 2.44 0.09
xvdb 0.01 0.00 1.02 8.94 127.97 598.53 145.79 0.00 0.43 1.78 0.28 0.25 0.25
xvdc 0.01 0.00 1.02 8.86 127.79 595.94 146.50 0.00 0.45 1.82 0.30 0.27 0.26
dm-0 0.00 0.00 0.69 2.32 10.47 31.69 28.01 0.01 3.23 0.71 3.98 0.13 0.04
dm-1 0.00 0.00 0.00 0.94 0.01 3.78 8.00 0.33 345.84 0.04 346.81 0.01 0.00
dm-2 0.00 0.00 0.09 0.07 1.35 0.36 22.50 0.00 2.55 0.23 5.62 1.78 0.03
[...]
^C
iostat
是了解块设备(例如磁盘)工作负载的重要工具。
r/s
、w/s
、rkB/s
、wkB/s
描述是每秒向设备提交的读取写入速率,性能问题可能仅仅源于负载过大await
是以毫秒为单位的 I/O 平均时间,这个数值超过预期暗示了是设备可能饱和或设备出现了问题avgqu-sz
表示向设备发出的平均请求数。大于 1 的值可能是饱和的证据%util
表示设备利用率,显示设备每秒工作的时间。这个值超过 60% 通常会导致性能不佳(应该同时会在await
上体现),接近 100% 的值通常表示饱和
磁盘 I/O 性能不佳并不一定导致应用程序的问题 —— 许多技术会选择异步执行 I/O,这样应用程序就不会阻塞。
7. free -m
$ free -m
total used free shared buff/cache available
Mem: 15738 1082 14143 0 792 14656
Swap: 8059 0 8059
只要 buffer/cache
不接近 0,那就很好。
8. sar -n DEV 1
sar
对系统当前的状态进行采样,然后通过计算数据和比例来展示系统的运行状态。本例中使用 -n DEV
专注于网络设备。
$ sar -n DEV 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
12:16:48 AM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
12:16:49 AM eth0 18763.00 5032.00 20686.42 478.30 0.00 0.00 0.00 0.00
12:16:49 AM lo 14.00 14.00 1.36 1.36 0.00 0.00 0.00 0.00
12:16:49 AM docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
^C
检查网络接口吞吐量 rxkB/s
和 txkB/s
,本例中 eth0 的接收速度为 20686.42 kB/s,换算过来差不多是 169 Mbps,考虑到千兆网卡的速率,远未达到上限。
9. sar -n TCP,ETCP 1
$ sar -n TCP,ETCP 1
Linux 5.14.0-284.25.1.el9_2.x86_64 (alma) 09/08/2023 _x86_64_ (10 CPU)
11:40:12 AM atmptf/s estres/s retrans/s isegerr/s orsts/s
11:40:13 AM 0.00 0.00 0.00 0.00 0.00
输出一些关键 TCP 指标的汇总视图:
active/s
表示每秒本地发起的 TCP 连接数(如connect()
)passive/s
表示每秒远端发起的 TCP 连接数(如accept()
)retrans/s
为每秒 TCP 重传次数
每秒连接数通常可用于粗略估计服务器的负载,而重传数可以观察网络或服务器是否出现了问题,结合其他工具判断到底是网络不可靠还是服务器因过载丢弃了数据包。
10. top
在 top
执行过程中可以使用的一些交互命令:
h
:显示帮助k
:终止一个进程i
:忽略闲置和僵死进程,这是一个开关式命令S
:切换到累计模式s
:改变两次刷新之间的延迟时间(单位为秒),有小数则换算成毫秒,输入 0 则不断刷新,默认刷新时间为 5 秒o
:改变显示项目的顺序l
:切换显示平均负载和启动时间信息m
:切换显示内存信息t
:切换显示进程和 CPU 状态信息c
:切换显示命令名称和完整命令行M
:根据驻留内存大小进行排序P
:根据 CPU 使用百分比大小进行排序T
:根据时间/累计时间进行排序w
:将当前设置写入$HOME/.toprc
Ctrl + s 可以暂停 top
的刷新,按下 Ctrl + q 继续。
后续分析
要继续深入挖掘,可以参考 Brendan 在 Velocity 2015 作的 Linux performance tools 讲座。