0%

【备忘录】Linux常见监控指标

本文总结了一些常见的Linux系统监控指标,和它们的计算方式,作为备忘笔记。

CPU使用率

CPU使用率衡量的是程序运行占用的CPU百分比。Linux的CPU使用率信息可以通过/proc/stat文件计算得到。/proc/stat包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累计的,单位为jiffies。如下图所示,cpu一行指的是总的CPU信息,cpu0、cpu1、cpu2、cpu3几行指的是CPU各个核的CPU信息。从这里也可以看出这台服务器共有4个核。每列从左到右的意思

  • user:从系统启动开始累计到当前时刻,用户态的CPU时间 ,不包含nice值为负进程所占用的时间
  • nice:从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间
  • system:从系统启动开始累计到当前时刻,内核态时间
  • idle:从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间
  • iowait:从系统启动开始累计到当前时刻,硬盘IO等待时间
  • irq:从系统启动开始累计到当前时刻,硬中断时间
  • softirq:从系统启动开始累计到当前时刻,软中断时间
  • steal:在虚拟环境下 CPU 花在处理其他操作系统的时间,Linux 2.6.11 开始才开始支持。
  • guest:在 Linux 内核控制下 CPU 为 guest 操作系统运行虚拟 CPU 的时间,Linux 2.6.24 开始才开始支持。
  • guest_nice: 在 Linux 内核控制下 CPU 为 guest 操作系统在虚拟 CPU 中运行nice进程的时间,Linux 2.6.33 开始才开始支持。
1
2
3
4
5
6
$ cat /proc/stat | grep cpu
cpu 180296 204 123070 30283108 13956 0 2046 0 0 0
cpu0 45360 53 30785 7560073 10631 0 771 0 0 0
cpu1 45266 47 30779 7573915 1373 0 508 0 0 0
cpu2 44442 54 30724 7574282 1257 0 405 0 0 0
cpu3 45228 48 30781 7574835 693 0 360 0 0 0

根据这些信息,就可以计算出CPU使用率。网管Agent的CPU使用率采集算法如下(以CPU0为例):

  • cat /proc/stat | grep ‘cpu0’得到cpu0的信息
  • cpu_total1=user+nice+system+idle+iowait+irq+softirq
  • cpu_used1=user+nice+system+irq+softirq
  • sleep 15秒
  • 再次cat /proc/stat | grep ‘cpu0’得到cpu的信息
  • cpu_total2=user+nice+system+idle+iowait+irq+softirq
  • cpu_used2=user+nice+system+irq+softirq
  • 得到cpu0在15秒内的平均使用率:(cpu_used2 - cpu_used1) / (cpu_total2 - cpu_total1) * 100%

每分钟会采集4次15秒内的CPU平均使用率。为了避免漏采集CPU峰值,可以取这一分钟内四次采集的最大值上报。

CPU负载

系统负载指的是计算机系统执行计算工作的表现,CPU负载指的是在一段时间内计算机的系统负载,一般用1分钟内、5分钟内、15分钟内这三个数字衡量。通过uptime命令可以显示CPU负载。

1
2
$ uptime
14:34:03 up 10:43, 4 users, load average: 0.06, 0.11, 0.09
  • 对于单核单CPU,CPU负载为0表示CPU完全空闲,CPU负载为1.00表示CPU恰好发挥其最大能力,CPU负载大于1表示系统过载,有进程正在等待调度
  • 对于多核或者多CPU系统,CPU负载为每个核的CPU负载总和

关于CPU负载的计算机制,可以参考我的另一篇博客

内存

free命令通过读取 /proc/meminfo,可以显示系统中的使用的和空闲的物理内存、Swap内存,同时也可以显示内核使用的buffer和cache,如下图所示。

1
2
3
4
$ free -w
total used free shared buffers cache available
Mem: 7773244 311800 2456280 872 233560 4771604 7169352
Swap: 0 0 0

其中各个字段意义为:

  • total:所有可以使用的内存(包括/proc/meminfo中的MemTotal和SwapTotal)
  • used:使用的内存,通过 total - free - buffers - cache 计算得到
  • free:没有使用的内存(包括/proc/meminfo中的MemFree和SwapFree)
  • shared:主要是指tmpfs使用的内存,现在已经废弃不用,总是为0
  • buffers:被内核Buffers使用的内存
  • cache:被内核的Page Cache和Slab使用的内存
  • buff/cache:buffers和cache的总和
  • available:对于开启一个新的应用还能使用多少内存的估计,不同于cache和free内存外,还考虑了page cache和可再回收的slab内存

磁盘IO

可以通过 iostat命令来监测磁盘的IO活动,它通过读取 /proc/diskstats文件来获取相关信息。

1
2
# cat /proc/diskstats
3 0 hda 446216 784926 9550688 4382310 424847 312726 5922052 19310380 0 3376340 23705160 0 0 0 0

hda后的各个参数含义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Field  1 -- # of reads completed
Field 2 -- # of reads merged, field 6 -- # of writes merged
为了提高IO的效率,两个相邻的读写操作会被合并,所以两个4K的读操作在提交给磁盘之前会被合并为一个8K的读操作,杜宇磁盘来说只会视作只有一个读操作。
Field 3 -- # of sectors read
Field 4 -- # of milliseconds spent reading
Field 5 -- # of writes completed
Field 6 -- # of writes merged
Field 7 -- # of sectors written
Field 8 -- # of milliseconds spent writing
Field 9 -- # of I/Os currently in progress
Field 10 -- # of milliseconds spent doing I/Os
Field 12 -- # of discards completed
Field 13 -- # of discards merged
Field 14 -- # of sectors discarded
Field 15 -- # of milliseconds spent discarding

跟记录CPU信息的/proc/stat文件一样,/proc/diskstats中每个字段的数值也是从系统启动后一直累加的。通过这些参数,可以计算出通过 iostat命令算出的参数,具体可以参考iostat 。我们用delta来表示在时间t内某个字段的增量。例如定义delta(reads merged)为当前reads merged的值减去t秒前reads merged的值

  • rrqm/s:delta(reads merged) / t (得到时间t内平均每秒reads merged的值)
  • wrqm/s:delta(writes merged) / t
  • r/s:delta(reads completed) / t
  • w/s:delta(writes completed) / t
  • rsec/s:delta(sectors read) / t
  • wsec/s:delta(sectors written) / t
  • rkB/s:delta(sectors read) / t / 2 (因为1 扇区为512字节,所以rkB/s为rsec/s的一半)
  • wkB/s:delta(sectors written) / t / 2
  • avgrq-sz:(delta(sectors read) + delta(sectors written)) / (delta(reads completed) + delta(writes completed))
  • avgqu-sz*delta(weighted time spent doing I/Os*) / t / 1000 (单位为毫秒,所以除以1000)
  • await:(delta(time spent reading) + delta(time spent writing)) / (delta(reads completed) + delta(writes completed))
  • svctm:delta(time spent doing I/Os)/ (delta(reads completed) + delta(writes completed))**
  • %util:delta(time spent doing I/Os) / t / 1000 * 100%

所有磁盘汇总采集项:

采集项 采集项说明 是否乘以100以保留精度
avgqu_sz_max 所有磁盘avgqu_sz最大值
svctm_time_max 所有磁盘svctm最大值
await_time_max 所有磁盘await最大值
util_max 所有磁盘%util最大值
disk_total_read 所有磁盘的r/s总和
disk_total_write 所有磁盘的w/s总和
磁盘IO disk_block_in 所有磁盘的rkB/s总和。bi即block in,表示从块设备(如磁盘)读取的块数。Linux块设备的块大小都为1024字节,所以disk_bi等于rkB/s。
磁盘IO disk_block_out 所有磁盘的rkB/s总和bo即block out,表示发给块设备的块数,即写磁盘。Linux块设备的块大小都为1024字节,所以disk_bi等于wkB/s。

单个磁盘采集项:

对于安装了1个以上的磁盘的服务器,可以采集单个磁盘的IO数据。最多支持24个盘。

采集项 采集项说明 是否乘以100以保留精度
disk_n_util(n为0-23) 第n个磁盘的%util值
disk_n_await 第n个磁盘的await值
disk_n_read 第n个磁盘的r/s值
disk_n_write 第n个磁盘的w/s值
disk_n_block_in 第n个磁盘的rkB/s值
disk_n_block_out 第n个磁盘的wkB/s值

网络IO

流量包量

通过/proc/net/dev文件,可以计算出服务器的流量及包量。

1
2
3
4
5
6
# cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 69570 1756 0 0 0 0 0 0 69570 1756 0 0 0 0 0 0
eth0: 2012939491 4197833 0 0 0 0 0 0 277523863 3280731 0 0 0 0 0 0
docker0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

与记录CPU信息的 /proc/stat文件类似,/proc/net/dev中的数值,也是从系统启动后一直累加的。

计算网卡流量方法如下:

  • 读取/proc/net/dev文件,获取eth0的Receive bytes、Receive packets、Transmit bytes、Transmit packets,分别记为receive_bytes0、receive_packets0、transmit_bytes0、transmit_packets0
  • sleep 60秒
  • 再次读取/proc/net/dev文件,获取eth0的Receive bytes、Receive packets、Transmit bytes、Transmit packets,分别记为receive_bytes1、receive_packets1、transmit_bytes1、transmit_packets1
  • 根据60秒前后的/proc/net/dev文件,便可计算出下面的指标:
    • 60秒内平均每秒入流量:(receive_bytes1 - receive_bytes0) * 8 / 60 / 1000 (kbps)(乘以8是为了把bytes转成bit,除以1000是为了把单位转成k,除以60则是取60秒内的平均值)
    • 60 秒内平均每秒出流量:(transmit_bytes1 - transmit_bytes0) * 8 / 60 / 1000 (kbps)
    • 60秒内平均每秒入包数:(receive_packets1 - receive_packets0) / 60 (个)
    • 60秒内平均每秒出包数:(transmit_packets1 - transmit_packets0) / 60 (个)

TCP连接数

/proc/net/snmp记录了一些TCP信息,其中比较有用的是 CurrEstab字段,即当前已建立的TCP连接数。

1
2
3
4
5
6
7
8
9
10
11
12
13
# cat /proc/net/snmp
Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates
Ip: 1 64 3527912 0 23 1893737 0 0 1634151 3266670 18 40 0 0 0 0 0 0 0
Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
Icmp: 92566 32 0 65 0 0 0 0 92501 0 0 0 0 0 93265 0 746 0 0 0 18 0 92501 0 0 0 0
IcmpMsg: InType3 InType8 OutType0 OutType3 OutType5
IcmpMsg: 65 92501 92501 746 18
Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts InCsumErrors
Tcp: 1 200 120000 -1 65567 687 59 249 8 1516787 1268763 805 4 33191 4
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti
Udp: 22034 822 0 21968 0 0 0 0
UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti
UdpLite: 0 0 0 0 0 0 0 0

UDP接收和发送数据报

/proc/net/snmp还记录了一些UDP信息,其中比较有用的是InDatagramsOutDatagrams字段。

UDP接收和发送数据报计算方法与 /proc/net/dev类似,步骤如下:

  • 读取/proc/net/snmp得到InDatagrams及OutDatagrams,分别记为in_data0和out_data0
  • Sleep 240秒
  • 再次读取/proc/net/snmp得到InDatagrams及OutDatagrams,分别记为in_data1和out_data1
  • 根据240秒前后的/proc/net/snmp文件,便可计算下面两个指标:
    • 240秒内平均每秒UDP入数据报:(in_data1 - in_data0) / 240
    • 240秒内平均每秒UDP出数据报:(out_data1 - out_data0) / 240
  • UDP数据每240上报一次。