一分钟Linux 性能问题分析定位
当你登录到一个有性能问题的 Linux 服务器,你在第一分钟检查什么?这应该是很多初学者的疑问, 在这篇文章中,将使用标准 Linux 工具,演示在命令行优化性能调查的1分钟内,来大致了解系统资源使用情况和正在运行的进程。寻找错误和饱和度指标,以及资源利用率。饱和是资源的负载超过其处理能力的地方,可以通过请求队列的长度或等待时间来暴露。
uptime
$ uptime
23:51:26 up 21:31, 1 user, load average: 30.02, 26.43, 19.02
这是一种查看平均负载的快速方法,平均负载指示要运行的任务(进程)的数量。在 Linux 系统上,这些数字包括想要在 CPU 上运行的进程,以及在不间断 I/O(通常是磁盘 I/O)中阻塞的进程。这给出了资源负载基础信息,值得快速浏览一下。这三个数字是指系统在1 分钟、5 分钟和 15 分钟内的负载平均值。这三个数字让我们了解负载如何随时间变化。例如,如果您被要求检查有问题的服务器,而 1 分钟的值远低于 15 分钟的值,那么您可能登录得太晚而错过了问题。在上面的示例中,负载平均值显示最近增加,1 分钟值达到 30,而 15 分钟值达到 19。这么大的数字意味着很多信息:可能是 CPU资源需求问题,命令vmstat 或 mpstat可以查看,接下来会介绍。
dmesg | tail
$ dmesg | tail
[1880957.563150] perl invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
[...]
[1880957.563400] Out of memory: Kill process 18694 (perl) score 246 or sacrifice child
[1880957.563408] Killed process 18694 (perl) total-vm:1972392kB, anon-rss:1953348kB, file-rss:0kB
[2320864.954447] TCP: Possible SYN flooding on port 7001. Dropping request. Check SNMP counters.
这会查看最近 10 条系统消息(如果有的话)。查找可能导致性能问题的错误。上面的示例包括 oom-killer 和 TCP 丢弃请求。不要错过这一步!dmesg 总是值得检查。
vmstat 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
34 0 0 200889792 73708 591828 0 0 0 5 6 10 96 1 3 0 0
32 0 0 200889920 73708 591860 0 0 0 592 13284 4282 98 1 1 0 0
32 0 0 200890112 73708 591860 0 0 0 0 9501 2154 99 1 0 0 0
32 0 0 200889568 73712 591856 0 0 0 48 11900 2459 99 0 0 0 0
32 0 0 200890208 73712 591860 0 0 0 0 15898 4840 98 1 1 0 0
vmstat是 virtual memory stat 的缩写,是一种常用工具。它在每一行打印关键服务器统计信息的摘要。vmstat 以参数 1 运行,以打印一秒钟的摘要。输出的第一行(在这个版本的 vmstat 中)有一些列显示自引导以来的平均值,而不是前一秒。
需要检查的列:
r:在 CPU 上运行并等待轮到的进程数。这提供了比平均负载更好的信号来确定 CPU 饱和度,因为它不包括 I/O。解释:大于 CPU 计数的“r”值是饱和的。
free:以千字节为单位的可用内存。如果要计算的数字太多,则您有足够的可用内存。作为命令 7 包含的“free -m”命令更好地解释了可用内存的状态。
si, so : 换入和换出。如果这些不为零,则说明您内存不足。
us, sy, id, wa, st:这些是所有 CPU 的平均 CPU 时间细分。它们是用户时间、系统时间(内核)、空闲、等待 I/O 和被窃取的时间(其他进程,或使用 Xen)。
CPU时间细分将通过添加用户+系统时间来确认CPU是否繁忙。恒定程度的等待I/O指向磁盘瓶颈;这是CPU空闲的地方,因为任务在等待挂起的磁盘I/O时被阻塞。您可以将等待I/O视为CPU空闲的另一种形式,它提供了有关它们空闲原因的线索。I/O 处理需要系统时间。如果系统时间平均值较高(超过 20%),需要进一步探索:内核可能正在低效地处理 I/O。在上面的示例中,CPU 时间几乎完全在用户级别,而是指向应用程序级别的使用。CPU 的平均利用率也超过 90%。这不一定是个问题:使用“r”列检查饱和度。
mpstat -P ALL 1
$ mpstat -P ALL 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
07:38:49 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
07:38:50 PM all 98.47 0.00 0.75 0.00 0.00 0.00 0.00 0.00 0.00 0.78
07:38:50 PM 0 96.04 0.00 2.97 0.00 0.00 0.00 0.00 0.00 0.00 0.99
07:38:50 PM 1 97.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 2.00
07:38:50 PM 2 98.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00
07:38:50 PM 3 96.97 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 3.03
此命令打印每个 CPU 的 CPU 时间细分,可用于检查不平衡。单个繁忙的 CPU 可能是单线程应用程序的原因。
pidstat 1
$ pidstat 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
07:41:02 PM UID PID %usr %system %guest %CPU CPU Command
07:41:03 PM 0 9 0.00 0.94 0.00 0.94 1 rcuos/0
07:41:03 PM 0 4214 5.66 5.66 0.00 11.32 15 mesos-slave
07:41:03 PM 0 4354 0.94 0.94 0.00 1.89 8 java
07:41:03 PM 0 6521 1596.23 1.89 0.00 1598.11 27 java
07:41:03 PM 0 6564 1571.70 7.55 0.00 1579.25 28 java
07:41:03 PM 60004 60154 0.94 4.72 0.00 5.66 9 pidstat
07:41:03 PM UID PID %usr %system %guest %CPU CPU Command
07:41:04 PM 0 4214 6.00 2.00 0.00 8.00 15 mesos-slave
07:41:04 PM 0 6521 1590.00 1.00 0.00 1591.00 27 java
07:41:04 PM 0 6564 1573.00 10.00 0.00 1583.00 28 java
07:41:04 PM 108 6718 1.00 0.00 0.00 1.00 0 snmp-pass
07:41:04 PM 60004 60154 1.00 4.00 0.00 5.00 9 pidstat
pidstat 有点像 top 的每个进程摘要,但打印滚动摘要而不是清除屏幕。这对于观察一段时间内的模式以及将您看到的内容(复制粘贴)记录到您的调查记录中很有用。上面的示例将两个 java 进程标识为负责消耗 CPU。%CPU 列是所有 CPU 的总数;1591% 表明 java 进程消耗了将近 16 个 CPU。
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
这是了解块设备(磁盘)、应用的工作负载和产生的性能的一个很好的工具。
- r/s、w/s、rkB/s、wkB/s:这些是每秒向设备传送的读取、写入、读取千字节数和写入千字节数。使用这些来表示工作负载。性能问题可能只是由于施加了过多的负载。
- await:I/O 的平均时间(以毫秒为单位)。这是应用程序遭受的时间,因为它包括排队时间和服务时间。大于预期的平均时间可能是设备饱和或设备问题的指示器。
- avgqu-sz:向设备发出的平均请求数。大于 1 的值可能是饱和的证据(尽管设备通常可以并行处理请求,尤其是面向多个后端磁盘的虚拟设备。)
- %util:设备利用率。这确实是一个繁忙的百分比,显示了设备每秒工作的时间。大于 60% 的值通常会导致性能不佳(应该在 await 中看到),尽管这取决于设备。接近 100% 的值通常表示饱和。
如果存储设备是一个逻辑磁盘设备,有许多后端磁盘,那么 100% 利用率可能只是意味着某些 I/O 正在 100% 的时间处理,但是后端磁盘可能远未饱和,并且可能能够处理更多的工作。另外,性能不佳的磁盘 I/O 不一定是应用程序问题。许多技术通常用于异步执行 I/O,因此应用程序不会阻塞并直接遭受延迟(例如,读取的预读和写入的缓冲)。
free -m
$ free -m
total used free shared buffers cached
Mem: 245998 24545 221453 83 59 541
-/+ buffers/cache: 23944 222053
Swap: 0 0 0
右侧两列显示:
buffers:用于缓冲区缓存,用于块设备 I/O。
cached:用于页面缓存,由文件系统使用。
我们只想检查它们的大小是否接近于零,这会导致更高的磁盘 I/O(使用 iostat 确认)和更差的性能。上面的例子看起来不错,每个都有很多兆字节。
“-/+ buffers/cache” 为已用和空闲内存提供了更少混淆的值。
Linux 使用空闲内存作为缓存,但如果应用程序需要它可以快速回收它。所以在某种程度上,缓存内存应该包含在空闲内存列中,这一行就是这样做的。另外,如果使用 Linux 上的 ZFS,因为 ZFS 有自己的文件系统缓存,free -m 列没有正确反映。看起来系统的可用内存不足,而实际上该内存可根据需要从 ZFS 缓存中使用。
sar -n DEV 1
$ 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
12:16:49 AM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
12:16:50 AM eth0 19763.00 5101.00 21999.10 482.56 0.00 0.00 0.00 0.00
12:16:50 AM lo 20.00 20.00 3.25 3.25 0.00 0.00 0.00 0.00
12:16:50 AM docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
使用此工具检查网络接口吞吐量:rxkB/s 和 txkB/s,作为工作负载的衡量标准,并检查是否已达到任何限制。在上面的示例中,eth0 接收速度达到 22 Mbytes/s,即 176 Mbits/sec(远低于 1 Gbit/sec 的限制)。
sar -n TCP,ETCP 1
$ sar -n TCP,ETCP 1
Linux 3.13.0-49-generic (titanclusters-xxxxx) 07/14/2015 _x86_64_ (32 CPU)
12:17:19 AM active/s passive/s iseg/s oseg/s
12:17:20 AM 1.00 0.00 10233.00 18846.00
12:17:19 AM atmptf/s estres/s retrans/s isegerr/s orsts/s
12:17:20 AM 0.00 0.00 0.00 0.00 0.00
12:17:20 AM active/s passive/s iseg/s oseg/s
12:17:21 AM 1.00 0.00 8359.00 6039.00
12:17:20 AM atmptf/s estres/s retrans/s isegerr/s orsts/s
12:17:21 AM 0.00 0.00 0.00 0.00 0.00
这是一些关键 TCP 指标的总结视图。这些包括:
active/s: 每秒本地启动的 TCP 连接数。
passive/s:每秒远程启动的 TCP 连接数。
retrans/s: 每秒 TCP 重传次数。
主动和被动计数通常可用于粗略衡量服务器负载:新接受的连接数(被动)和下游连接数(主动)。将主动视为出站,将被动视为入站可能会有所帮助,但这并非严格如此(例如,考虑本地主机到本地主机的连接)。重新传输是网络或服务器问题的标志;它可能是一个不可靠的网络(例如,公共互联网),或者可能是由于服务器过载和丢弃数据包。上面的例子显示每秒只有一个新的 TCP 连接。
top命令
$ top
top - 00:15:40 up 21:56, 1 user, load average: 31.09, 29.87, 29.92
Tasks: 871 total, 1 running, 868 sleeping, 0 stopped, 2 zombie
%Cpu(s): 96.8 us, 0.4 sy, 0.0 ni, 2.7 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 25190241+total, 24921688 used, 22698073+free, 60448 buffers
KiB Swap: 0 total, 0 used, 0 free. 554208 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20248 root 20 0 0.227t 0.012t 18748 S 3090 5.2 29812:58 java
4213 root 20 0 2722544 64640 44232 S 23.5 0.0 233:35.37 mesos-slave
66128 titancl+ 20 0 24344 2332 1172 R 1.0 0.0 0:00.07 top
5235 root 20 0 38.227g 547004 49996 S 0.7 0.2 2:02.74 java
4299 root 20 0 20.015g 2.682g 16836 S 0.3 1.1 33:14.42 java
1 root 20 0 33620 2920 1496 S 0.0 0.0 0:03.82 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.02 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:05.35 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
6 root 20 0 0 0 0 S 0.0 0.0 0:06.94 kworker/u256:0
8 root 20 0 0 0 0 S 0.0 0.0 2:38.05 rcu_sched
top 命令包括我们之前检查的许多指标。运行它可以很方便地查看是否有任何内容与之前的命令有很大不同,这表明负载是可变的。top 的缺点是随着时间的推移难看到之前的记录,这在提供滚动输出的 vmstat 和 pidstat 等工具中可能更清楚。另外,想暂停,或者截取top命令的输出可以通过过快捷键 Ctrl-S 暂停,Ctrl-Q 继续 来实现。
浙公网安备 33010602011771号