Linux健康状态观测

介绍CPU、内存、I/O的一些基本知识,以及评估它们性能的命令

CPU

首先介绍计算机中最重要的计算组件:中央处理器。一般我们可以通过top命令来观测它的性能。

top命令

top命令可用于观测CPU的一些运行指标。如图,进入top命令之后,按1键即可看到每核CPU的详细状况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
top - 10:11:08 up 53 min,  0 users,  load average: 0.02, 0.40, 0.60
Tasks: 22 total, 1 running, 21 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu4 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu5 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu6 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu7 : 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 12674.5 total, 10289.8 free, 799.1 used, 1585.6 buff/cache
MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 11596.8 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1212 chris 20 0 796216 125936 35944 S 0.3 1.0 0:14.95 node
1 root 20 0 908 532 468 S 0.0 0.0 0:00.03 init
8 root 20 0 896 88 20 S 0.0 0.0 0:00.00 init
9 root 20 0 896 88 20 S 0.0 0.0 0:00.63 init
10 chris 20 0 17108 8972 5324 S 0.0 0.1 0:06.44 zsh
845 root 20 0 1256 380 20 S 0.0 0.0 0:00.00 init
846 root 20 0 1256 380 20 S 0.0 0.0 0:00.00 init
847 chris 20 0 2612 592 524 S 0.0 0.0 0:00.00 sh
848 chris 20 0 2612 596 528 S 0.0 0.0 0:00.00 sh
853 chris 20 0 2612 532 464 S 0.0 0.0 0:00.00 sh
857 chris 20 0 944412 84200 35016 S 0.0 0.6 0:07.16 node
868 root 20 0 1264 380 20 S 0.0 0.0 0:00.00 init

CPU的使用有多个维度的指标,以下分别说明一下:

  • us 用户态所占用的CPU百分比。

  • sy 内核态所占用的CPU百分比。如果这个值过高,需要配合vmstat命令,查看是否是上下文切换是否频繁。

  • ni 高优先级应用所占用的CPU百分比。

  • wa 等待I/O设备所占用的CPU百分比。如果这个值非常高,输入输出设备可能存在非常明显的瓶颈。

  • hi 硬件中断所占用的CPU百分比。

  • si 软中断所占用的CPU百分比。

  • st 这个一般发生在虚拟机上,指的是虚拟CPU等待实际CPU时间的百分比。如果这个值过大,则你的宿主机压力可能过大。如果你是云主机,则你的服务商可能存在超卖。

  • id 空闲CPU百分比。

一般的,我们比较关注空闲CPU的百分比,它可以从整体上体现CPU的利用情况。

负载

我们还要评估CPU任务执行的排队情况,这些值就是负载(load)。top命令,显示的CPU负载,分别是最近1分钟、5分钟、15分钟的数值。

1
2
3
4
5
top - 10:15:34 up 58 min,  0 users,  load average: 0.00, 0.15, 0.44
Tasks: 22 total, 1 running, 21 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 12674.5 total, 10282.0 free, 802.3 used, 1590.2 buff/cache
MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 11593.6 avail Mem

以单核操作系统为例,将CPU资源抽象成一条单向行驶的马路。则会发生三种情况:

  • 马路上的车只有4辆,车辆畅通无阻,load大约是0.5。

  • 马路上的车有8辆,正好能首尾相接安全通过,此时load大约为1。

  • 马路上的车有12辆,除了在马路上的8辆车,还有4辆等在马路外面,需要排队。此时load大约为1.5。

那load为1代表的是啥?针对这个问题,误解还是比较多的。

很多同学认为,load达到1,系统就到了瓶颈,这不完全正确。load的值和cpu核数息息相关。举例如下:

  • 单核的负载达到1,总load的值约1。

  • 双核的每核负载都达到1,总load约2。

  • 四核的每核负载都达到1,总load约为4。

所以,对于一个load到了10,却是16核的机器,你的系统还远没有达到负载极限。通过uptime命令,同样能够看到负载情况。

vmstat

要看CPU的繁忙程度,还可以通过vmstat命令。下面是vmstat命令的一些输出信息。

1
2
3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 10528708 125908 1502728 0 0 18 227 14 46 4 0 96 0 0

我们比较关注的有下面几列:

  • b 存在于等待队列的内核线程数目,比如等待I/O等。数字过大则cpu太忙。

  • cs 代表上下文切换的数量。如果频繁的进行上下文切换,就需要考虑是否是线程数开的过多。

  • si/so 显示了交换分区的一些使用情况,交换分区对性能的影响比较大,需要格外关注。

内存

top命令可以看到几列数据
  • VIRT 这里就是虚拟内存,一般比较大,不用做过多关注。

  • RES 我们平常关注的就是这一列的数值,它代表了进程实际占用的内存。平常在做监控时,也主要是监控这个数值。

  • SHR 指的是共享内存,比如可以复用的一些so文件等

CPU缓存

由于CPU核内存之间的速度差异是非常大的,解决方式就是加入高速缓存。其实,这些高速缓存,往往会有多层

ava有大部分知识点是围绕多线程的,那是因为,如果一个线程的时间片跨越了多个CPU,那么就会存在同步问题。

在Java中,最典型的和CPU缓存相关的知识点,就是并发编程中,针对Cache line的伪共享(false sharing)问题。

伪共享是指:在这些高速缓存中,是以缓存行为单位进行存储的。哪怕你修改了缓存行中一个很小很小的数据,它都会整个的刷新。所以,当多线程修改一些变量的值时,如果这些变量在同一个缓存行里,就会造成频繁刷新,无意中影响彼此的性能。

零拷贝

kafka比较快的一个原因就是使用了zero copy。所谓的Zero copy,就是在操作数据时, 不需要将数据buffer从一个内存区域拷贝到另一个内存区域。因为少了一次内存的拷贝, CPU的效率就得到提升

要想将一个文件的内容通过socket发送出去,传统的方式需要经过以下步骤:

  • 将文件内容拷贝到内核空间。

  • 将内核空间的内容拷贝到用户空间内存,比如Java应用。

  • 用户空间将内容写入到内核空间的缓存中。

  • socket读取内核缓存中的内容,发送出去。