服务器出现性能问题,第一分钟应该干啥?
Oct 15, 2020 21:30 · 2276 words · 5 minute read
Linux 服务器出现性能问题,第一分钟应该干啥?
在 60 秒内,你可以通过下面一套连招来全面了解系统资源的使用情况和进程的运行状况:
$ 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
1. uptime
$ uptime
23:51:26 up 21:31, 1 user, load average: 30.02, 26.43, 19.02
快速查看平均负载。在 Linux 系统中,这堆数字代表等待 CPU 和因不可中断 I/O 阻塞的进程数量。这就对资源负载心里有数了,值得一看。
三个数字分别是 1、5、15 分钟内的平均值,通过它们也可以了解一下负载随时间的变化趋势。举个栗子,如果你被喊过去检查出问题的服务器,但是最近 1 分钟的值远小于 15 分钟,那就来晚了。
2. 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 被干掉和 TCP 丢包。
说不定在这就被你捉到呢~
3. 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 一般都预装的。
r
就绪队列,正在占用和等待 CPU 的进程数量。这个比平均负载更有价值,因为它不包括 I/O 阻塞的那些。free
空闲内存,如果位数多到你数不过来就别看了,内存足够。si, so
换入和换出,如果都不为 0,说明内存用完了。us
,sy
,id
,wa
,st
这些都是 CPU 时间相关的,分别是运行非内核态代码的时长、运行内核态代码的时长、空闲时间(包括等待 I/O 时间)、等待 I/O 时间和虚拟机的“窃取”时间。
非内核态 + 内核态代码运行时间越长 CPU 越忙。I/O 等待时间长表示磁盘遇到性能瓶颈,CPU 虽处于空闲状态,但是任务都被磁盘 I/O 给阻塞了。
I/O 操作需要在内核态运行。如果平均内核态时间高于 20%,需要进一步研究:有可能内核在低效地处理 I/O。
4. mpstat -P ALL 1
$ mpstat -P ALL 1
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 分工状态。一核有难七核围观说明这是一个单线程应用。
5. pidstat 1
$ pidstat 1
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 是资源消耗大户,1591% 都快吃掉 16 核了。。。
6. iostat -xz 1
$ iostat -xz 1
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
请求处理完成等待时间,包括了排队和处理的时间。大于平均的逾期时间时设备可能已饱和或出问题。avgqu-sz
发送给设备的平均 I/O 请求数(平均 I/O 队列长度)。大于 1 表示可能饱和了(尽管设备通常可以并行处理,尤其是有多个磁盘的虚拟设备)%util
设备使用率。超过 60% 就要小心了(await
会有反应的)。
如果存储设备是拥有多个后端磁盘的逻辑磁盘设备,100% 就不一定饱和了。
要记住的是有性能问题的磁盘 I/O 并不一定是应用程序的问题,通常都利用异步 I/O 来使应用程序不被阻塞。
7. 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/Ocached
(页)缓存是文件系统用的
检查一下内存情况,内存耗尽可能会导致更重的磁盘 I/O(使用 iostat 确认)。
Linux 会将空闲的内存用作缓存,但是一旦应用程序需要就收回。
如果在 Linux 上使用 ZFS,可能会凌乱,因为 ZFS 有自己的文件系统缓存,free -m
不准。
8. sar -n DEV 1
$ sar -n DEV 1
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
用 sar 检查网卡吞吐量(rxkB/s
和 txkB/s
)。
9. sar -n TCP,ETCP 1
$ sar -n TCP,ETCP 1
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 连接从关闭状态直接转换到 SYN-SENT 状态的次数。passive/s
:每秒 TCP 连接从监听状态直接转换到 SYN-RCVD 状态的次数。retrans/s
:每秒 TCP 重传次数。
retrans/s
和 passive/s
次数通常用于估算服务器负载。
重传是网络或服务器有问题的迹象:可能是网不可靠;也有可能是服务器因过载而丢包。
10. 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 最大的问题是输出之前会清屏,历史数据也就丢失了。
后续分析
还有更多命令和工具来深入挖掘,看下 Brendan 的 Linux Performance Tools tutorial,涉及 40 多个命令来观察、基准测试、性能调整、分析和追踪。