你登录进一台有性能问题的Linux
服务器,第一时间内你会检查什么?
在第一分钟,你可以通过运行下面十条命令获取大致的系统资源使用率和运行进程。寻找错误和饱和度指标,因为它们都很容易解释,然后是资源利用率。饱和度是资源的负载超过其处理能力的地方,可以通过请求队列的长度或等待时间来暴露。
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
有些命令需要安装sysstat
。这些命令公开的指标将帮助完成USE方法的度量。(USE方法全称 Utilization Saturation and Errors,一种定位性能瓶颈的方法)。这涉及检查所有资源(CPU、内存、磁盘等)的利用率、饱和度和错误指标。还要注意何时检查和排除资源,因为通过排除过程,这会缩小要研究的目标范围,并指导任何后续调查。
以下小节总结了这些命令,并附有来自生产系统的示例。有关这些工具的更多信息,请参阅它们的手册页。
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分钟内负载还低,说明你登录时间太晚,错过了问题发生时间。
在上面例子,说明负载在上升中。
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
丢弃一个请求。
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
^C
vmstat
是虚拟内存状态的缩写,是一个非常有用的工具,它在每一行打印出服务器关键统计信息的概要。
vmstat 1
是表示每一秒打印一次。每一行都有一些列都是表示自从系统启动以来的平均值,而不是刚刚过去的那一秒。
要检查的列:
r
: 有多少进程正在运行free
: 空闲内存(以K为单位)si
,so
: 交换入和出的数目(内存和交换空间)。如果不是0,说明内存不足us
,sy
,id
,wa
,st
: 使用的CPU
时间,是每个CPU的平均值,分别为用户态,系统,空闲,等待I/O
时间,被偷掉的时间(主要是虚拟机)用户态时间和系统时间的相加,可以用来确定系统是否繁忙。固定的等待I/O
时间表示有磁盘瓶颈,,因为任务被阻塞等待挂起的磁盘 I/O。您可以将等待 I/O 视为另一种形式的 CPU 空闲,它提供了有关它们空闲原因的线索。
I/O
处理需要系统时间。如果系统时间平均值较高(超过 20%),进一步探究可能会很有趣:内核可能正在低效地处理 I/O。
在上面例子,CPU
时间基本上是花费在用户态,说明都是由应用程序使用。这说明并不是一个问题。
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之间的负载不平衡。单个繁忙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
^C
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
[...]
^C
这是一个很强的工具,用来理解块设备的工作量和相应的性能。
请看:
r/s
, w/s
,rkB/s
,wkB/s
:这是设备每秒的读写次数和读写数据量(用k字节表示),可用于衡量设备工作量。一个性能问题很多时候仅仅是磁盘过高的读写。await
:I/O
读写的平均时间,以毫秒计算。这个时间包括正在处理和堵塞在队列的时间。大于预期的平均时间指示着设备过度饱和或设备故障。avgqu-sz
: 向设备发送的请求的平均数。数字大于1会是设备饱和的标志,虽然设备可能并行请求,特别是后面挂载着多个磁盘的虚拟设备。%util
:设备使用率。这是一个繁忙百分比,表示着每秒设备工作的百分比。数值超过60%,性能就会劣化。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
使用空闲内存做缓存,在应用程序需要分配内存时就会回收,减少缓存。所以,在某种方面,缓存应该是包括在空闲内存这一列。
如果文件系统是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
^C
通过查看rxkB/s
和txkB/s
来查看网络接口的吞吐,看是否达到了阈值。比如上面,网络接口eth0
接收达到176M/s,离1G/s限制还远着呢。
%ifutil
是用来看设备利用率的,它的结果很多时候是不准确的,比如在这个例子,只是0%,正常应该是0.17。
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
^C
这是一些主要TCP
度量的概览,包括:
active/s
:每秒本地发起TCP
连接数passive/s
:每秒远程连接过来的TCP
连接数retrans/s
:每秒重传的TCP
包数量active
和passive
的数目粗略地度量服务器的工作量:接收的连接数(passive
)和发起的连接数(active
)。
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
这个命令可以显示很多信息,很容易找出哪些进程是异常的。但它的缺陷是,没办法进行跟踪对比。
暗号:05bef