原文链接:https://netflixtechblog.com/linux-performance-analysis-in-60-000-milliseconds-accc10403c55。本文只是处于学习目的,转载请注明,翻译水平有限。

Linux性能分析60秒

当你登录到一台有性能问题的Linux服务器上时,前1分钟你该检查什么?

Netflix有大量的EC2Linux云主机,并且有大量的性能分析工具来监控和检查服务器的性能。包括云层面监控的Atlas和根据需求进行实例分析的Vector。虽然这些工具能帮助我们分析很多问题,但有时我们需要登录的主机实例上运行标准的Linux性能工具。

First 60 Seconds: Summary前60秒总览

Netflix性能工程师团队将展示在检查性能的前60秒使用的命令行。在这60秒钟你可以使用下面的10个命令得到系统资源使用和运行进程的总览情况。使用这些命令首先要检查错误,查看饱和度指标,因为这两项很好解释,接着是资源的使用率。饱和度是一项资源负载较大,超过了其处理能力,通常会以请求队列的长度或等待时间的方式来展示。

使用到的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

上面的命令有的需要安装sysstat包。这些命令展示的指标有助于你完成USE方法的需求:USE是用于定位性能瓶颈的方法论。它包括检查所有资源(CPU,MEM,Disk等)的使用率,饱和度,和错误事件。

接下来是这些命令在生产系统的使用示例,这些工具的详情可以通过man手册查询。

1 uptime

$ uptime 
23:51:26 up 21:31, 1 user, load average: 30.02, 26.43, 19.02

这是查看系统平局负载的快速方式,平均负载显示了系统当前想要运行的进程数量。在Linux系统中,这个数值包含即将运行的进程数量和不可终端IO进程数量。这个给出了一个较高层面的资源负载情况。如果不借助其他工具,对此种负载情况并不能产生正确的理解。

在上面的示例中,平均负载在增加。数值很大,意味着很多东西:可能是CPU需求增加。使用vmstatmpstat命令可以进一步确认具体情况。

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-killer和TCP dropping a request。

千万不能错过这一步,dmesg永远值得检查。

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
^C

上面是虚拟内存状态的简短信息。vmstat(8)是一个通用的工具(十几年前为BSD系统首次创建)。此工具会输出服务器关键统计信息总览。

vmstat的参数1,表示每1秒的总体情况。在输出的列中,有些是自开机以来的平均值,而不是前一秒的情况。现在让我们跳过第一行,除非你想记住每一列是什么。

需要检查的列

如果CPU繁忙,则CPU分解可以通过user time + system time确定。对于disk瓶颈,则wait I/O是个常数。因为task因为等待pending状态的disk I/O而阻塞,则此时CPU处于idle状态。你可以将等待I/O视为另一种形式的CPU idle状态,这可以给出一个提示,为什么CPU处于idle状态。

system time对于I/O处理是必须的。较高的平均系统时间,超过20%,就应该深入检查一下:可能kernel正在处理低效的I/O.

上面的示例中,CPU的时间几乎全在用户级别,指向应用级别。CPU的平均使用率超过了90%。但这不是构成问题的必须条件。使用r列检查饱和度。

4 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的使用率较高的话,可以证明应用是单线程的。

5 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的每个进程的概览情况有点相似,但输出的是一个滚动的概览情况,而不是在屏幕动态显示。这对在一段时间内观察非常有帮助,同时也支持将你看到的记录的你的调查中(copy-n-paste)

上面的示例表明主要是两个Java进程在消耗CPU。%CPU一栏是所有CPU的综合,所以1591%表明Java进程几乎占用了16个CPU。

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是用于理解块设备(磁盘)的强大工具,它涵盖了应用负载和性能结果。检查下面几项:

如果存储设备是个逻辑磁盘设备,位于多个后端磁盘的前面,则100%的使用率仅表明一些I/O正在被处理,占用100%的时间,但后端的磁盘离饱和还很远呢,并可以处理更多的工作。

需要记住的是较差的disk I/O性能并不是应用问题的必要条件。有许多技术可以用来进行I/O异步操作,因此应用并不会阻塞,也不会直接忍受延迟(比如read-ahead for reads, and buffering for writes).

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

右边的两列表示:

我们需要检查它们的大小不接近0,因为那样可能导致较高的磁盘I/O(通过iostat确认),和较差的性能。上面的示例看起来还不错,每个都有很多MB。

“-/+ buffers/cache”用于使用的和空闲的内存并不会带来很强的混淆。Linux使用空闲内存用于cache,如果应用需要,cache可以被快速回收。因此cached的内存应该包含在空闲内存一栏。网站有关于这个问题的描述。

如果在Linux上使用ZFS,则会进一步混淆。因为ZFS有其自己独立的文件系统cache,因此free -m并不能直接正确的反应出来。

8 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 and txkB/s指标用于测量工作负载。另外还要检查是否达到了某些限制。上面的示例中,eth0接受达到了22 Mbytes/s,即176Mbits/sec (well under, say, a 1 Gbit/sec limit可以说在1 Gbit/sec limit内)

这个版本有%ifutil一列,用于表示设备使用率(max of both directions for full duplex),这项有时有采用Brendan’s nicstat tool工具测量。

9 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和passive计数对于粗略的测量服务器负载是比较有用的:新accepted连接数(passive),下游连接数(active)。可以将active视为出口流量,passive视为进入流量。但这并不是严格的准确(如localhost到localhost的连接)

重传是网络问题或服务器问题的信号;可能是网络不稳定(如公网),或服务器因为过载而丢包。上面的示例显示每秒仅有一个新的TCP连接。

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很容易看到前面命令查找的指标,哪个负载在变化。top不好的地方在于很难在一个时间段内找到规律。但这对于vmstat和pidstat工具来说是非常容易的。如果你不能够快速的暂停输出(Ctrl-S to pause, Ctrl-Q to continue),则很容易存过中间的可能的有用信息。

Follow-on Analysis

还有更多的工具和方法等待你去发掘和使用。参见Brendan在 Velocity 2015分享的Linux Performance Tools tutorial,本次分享涉及到了40多个命令,包含observability, benchmarking, tuning, static performance tuning, profiling, and tracing。

Reference