来自公众号:新世界杂货铺
本着“拿来主义”的精神,吸收他人长处为己用。老许翻译一篇 Linux 性能分析相关的文章分享给各位读者,同时也加深自己的印象。
你登录到具有性能问题的 Linux 服务器时,第一分钟要检查什么?
在 Netflix,我们拥有庞大的 Linux EC2 云实例,以及大量的性能分析工具来监视和调查它们的性能。这些工具包括Atlas
和Vector
。Atlas
用于全云监控,Vector
用于按需实例分析。这些工具能帮助我们解决大部分问题,但有时候我们仍需登录实例并运行一些标准的 Linux 性能工具。
Atlas:根据 github 上面的文档老许简单说一下自己的认知。一个可以管理基于时间维度数据的后端,同时具有内存存储功能可以非常快速地收集和报告大量指标。
Vector:Vector 是一个主机上的性能监视框架,它可以将各种指标展示在工程师的浏览器上面。
总结
在这篇文章中,Netflix 性能工程团队将向您展示通过命令行进行性能分析是,前 60 秒应该使用那些 Linux 标准工具。在 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
复制代码
其中一些命令需要安装 sysstat 软件包。这些命令暴露的指标是一种帮助你完成USE Method(Utilization Saturation and Errors Method)
——一种查找性能瓶颈的方法。这涉及检查所有资源(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 分钟的值,则意味着你可能登录的太晚而错过了问题现场。
在上面的例子中,最近的平均负载增加,一分钟值达到 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
^C
复制代码
vmstat 是虚拟内存状态的缩写。它在每一行上打印关键服务的统计信息。
vmstat 在参数 1 下运行,以显示一秒钟的摘要。在某些版本中,第一行的某些列展示的是自启动以来的平均值,而不是前一秒的平均值。现在请跳过第一行,除非你想学习并记住那一列是那一列。
要检查的列:
r:在 CPU 上运行并等待切换的进程数。这为确定 CPU 饱和比平均负载提供了更好的信号,因为它不包括 I/O。简单来说就是:r 的值大于 CPU 数量即为饱和状态。
free:可用内存以字节为单位,如果数字很大,则说明你有足够的可用内存。free -m
命令能够更好的描述此状态。
si, so:swap-ins 和 swap-outs. 如果这两个值不为 0,则说明内存不足。
us, sy, id, wa, st:这是总 CPU 时间的百分比。他们分别是用户时间、系统时间(内核)、空闲时间(包括 I/O 等待)、I/O 等待和被盗时间(虚拟机所消耗的时间)。
最后关于 us, sy, id, wa, st 的解释和原文不太一样,所以老许贴一下 vmstat 手册中的解释。
通过用户时间+系统时间来确认 CPU 是否繁忙。如果有持续的等待 I/O,意味着磁盘瓶颈。这是 CPU 空闲的时候,因为任务等待 I/O 被阻塞。你可以将 I/O 等待视为 CPU 空闲的另一种形式,同时它也提供了 CPU 为什么空闲的线索。
I/O 处理需要消耗系统时间。一个系统时间占比较高(比如超过 20%)值得进一步研究,可能是内核处理 I/O 的效率低下。
在上面的例子中,CPU 时间几乎完全处于用户级别,即 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
^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:分别表示每秒交付给设备的读写请求数和每秒读写的 KB 数。这些可以描述设备的工作负载。性能问题可能仅仅是由于施加了过多的负载。
await:I/O 处理时间(毫秒为单位),这包括队列中请求所花费的时间以及为请求服务所花费的时间。如果值大于预期的平均时间,可能是因为设备已经饱和或设备出现问题。
avgqu-sz:发送给设备请求的平均队列长度。该值大于 1 表明设备已达饱和状态(尽管设备通常可以并行处理请求,尤其是有多个后端磁盘的虚拟设备)。
%util:设备利用率。这是一个显示设备是否忙碌的百分比,其含义为设备每秒的工作时间占比。该值大于 60%时通常会导致性能不佳(可以在 await 中看出来),不过它也和具体的设备有关。值接近 100%时,意味着设备已饱和。
关于 avgqu-sz 的解释和原文不太一样,所以老许贴一下 iostat 手册中的解释。
如果存储设备是位于很多磁盘前面的逻辑磁盘设备,则 100%利用率可能仅仅意味着所有时间都在处理 I/O,但是后端磁盘可能远远还没有饱和,而且还能处理更多的工作。
请记住,磁盘 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:页缓存,用于文件系统。
我们检查他们的值是否接近 0,接近 0 会导致更高的磁盘 I/O(可以通过 iostat 来确认)以及更糟糕的磁盘性能。上面的示例看起来不错,每个值都有许多兆字节。
-/+ buffers/cache
为已用内存和可用内存提供更加清晰的描述。Linux 将部分空闲内存用作缓存,但是在应用程序需要时可以快速回收。因此,用作缓存的内存应该应该以某种方式包含在 free 这一列,-/+ buffers/cache
这一行就是做这个事情的。
上面这一段翻译,可能比较抽象,感觉说的不像人话,老许来转述成人能理解的话:
total = used + free
used = (-/+ buffers/cache 这一行 used 对应列) + buffers + cached
=> 24545 = 23944 + 59 + 541
free = (-/+ buffers/cache 这一行 free 对应列) - buffers - cached
=> 221453 = 222053 - 59 - 541
如果在 Linux 使用了 ZFS 会令人更加疑惑(就像我们对某些服务所做的一样),因为 ZFS 有自己的文件系统缓存。而free -m
并不能正确反应该文件系统缓存。它可能表现为,系统可用内存不足,而实际上该内存可根据需要从 ZFS 缓存中使用。
ZFS: Zettabyte File System,也叫动态文件系统,更多信息见百度百科
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 的接受速度达到 22Mbyte/s(176Mbit/s),该值远低于 1Gbit/s 的限制。
原文中无 rxkB/s 和 txkB/s 的解释,老许特意找了使用手册中的说明。
这个版本还有 %ifutil 作设备利用率,这也是我们使用 Brendan 的 nicstat 工具来测量的。和 nicstat 工具一样,这很难正确,而且本例中看起来该值并不起作用。
老许试了一下自己的云服务发现 %ifutil 指标并不一定都有。
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 连接数通常用于服务器负载的粗略度量。将 active 视为向外的连接,passive 视为向内的连接可能会有帮助,但这样区分并不严格(例如,localhost 连接到 localhost)。
重传是网络或服务器出问题的迹象。它可能是不可靠的网络(例如,公共 Internet),也可能是由于服务器过载并丢弃了数据包。上面的示例显示每秒仅一个新的 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 之类提供滚动输出的工具则能体现的更加清楚。如果你没有足够快地暂停输出(Ctrl-S 暂停, Ctrl-Q 继续),随着屏幕的清除间歇性问题的证据很有可能丢失。
最后,衷心希望本文能够对各位读者有一定的帮助。
翻译原文
https://netflixtechblog.com/linux-performance-analysis-in-60-000-milliseconds-accc10403c55
评论