前言

image-20240516145620615

Linux Performance

CPU篇

CPU性能指标

CPU使用率

  • 用户CPU使用率:CPU使用率高,通常说明有应用程序比较繁忙。
  • 系统CPU使用率:CPU使用率高,说明内核比较繁忙。
  • 等待I/O的CPU使用率:iowait,表示等待I/O的时间百分比,iowait高通常说明系统与硬件设备I/O交互时间比较长。
    • iowait指的是CPU等待硬盘I/O(输入/输出)操作完成的时间百分比。在这种状态下,CPU没有执行任何代码,因为它正在等待硬盘的I/O操作完成。
  • 软中断和硬中断的CPU使用率,内核调用软中断处理程序,硬中断处理程序的百分比。

平均负载

平均负载其实就是平均活跃进程数。平均负载大于CPU数量表示CPU不足以服务线程,有些线程在等待;如果平均负载小于CPU数量,这代表还有一些余量。

主要包括三个数值,分别值过去1分钟,5分钟,15分钟的平均负载。

平均负载与 CPU 使用率关系:平均负载是指单位时间内,处于可运行状态和不可中断状态的进程数。【可运行状态是指正在使用或等待使用 CPU,而不可中断状态是指进程正执行某种 I/O 操作,比如读写磁盘】。所以,它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。

  • CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时这两者是一致的;
  • I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
  • 大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。

上下文切换

频繁上下文切换,将时间消耗在寄存器、内核栈以及虚拟内存等数据保持与恢复上。切换分为以下两类:

  • 无法获取资源而导致的自愿上下文切换。

  • 被系统强制调度导致的非自愿上下文切换。

CPU缓存命中率

CPU速度比内存访问速度快得多,协调这两者巨大性能差距,使用CPU缓存。缓存的是热点的内存数据。L1 L2 L3到缓存。L1 L2常用在单核中,L3则用在多核中。L1->L3三级缓存大小依次增大,相应性能依次降低。命中率衡量的是CPU缓存的复用情况,命中率越高,则性能越好。

常用命令

命令 描述
uptime 平均负载
vmstat 包括系统范围的CPU平均负载,上下文切换次数、中断次数、还包括处于运行和不可中断状态的进程数量
mpstat 单个CPU统计信息和软中断次数
sar 统计历史信息
ps 进程状态和CPU使用率
top 监控平均负载,运行队列、整体CPU使用率,以及每个进程/线程CPU用量
pidstat 每个进程/线程CPU用量分解
time 给一个命令计时,带CPU用量分解
Dtrace,perf CPU剖析和跟踪
perf CPU性能计数器分析,CPU缓存,cpu调度

uptime

功能:打印平均负载,系统运行时间

1
2
(base) sv@sv-NF5280M5:/home/sv$ uptime
10:56:18 up 72 days, 20:32, 2 users, load average: 25.44, 25.69, 25.18

最后三个数字是1,5,15分钟内的平均负载。通过这三个值可以判断系统负载在此段时间内上升,下降还是平稳。

如果 1 分钟、5 分钟、15 分钟的三个值基本相同,或者相差不大,那就说明系统负载很平稳。

把系统的平均负载监控起来,然后根据更多的历史数据,判断负载的变化趋势,一般当平均负载高于 CPU 数量 70% 的时候,应该分析排查负载高的问题。

查看几个 CPU数量【lscpu】

1
2
(base) sv@sv-NF5280M5:/home/sv$ grep 'model name' /proc/cpuinfo | wc -l
40

vmstat

(Vitual Memory Static)

功能:报告虚拟内存统计信息

具体使用vmstat --help查看详细用法。

选项 功能
-a 显示活跃和非活跃内存
-f 显示从系统启动至今的fork数量
-m 显示slabinfo
-s 显示内存相关统计信息及多种系统活动数量
-d 显示磁盘相关的统计信息
-S 使用指定单位显示。参数有 k 、K 、m 、M ,分别代表1000、1024、1000000、1048576字节(Byte),默认单位为K(1024 Bytes)
delay 刷新时间间隔,如果不指定,只显示一条结果
count 刷新次数,如果不指定刷新次数,但指定了刷新时间间隔,这时刷新次数为无穷
1
2
3
4
5
# 间隔 1 秒后输出 1 组数据
(base) sv@sv-NF5280M5:/home/sv$ vmstat 1 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b 交换 空闲 缓冲 缓存 si so bi bo in cs us sy id wa st
23 0 1719692 7783592 400820 23694264 0 0 1 4 0 0 46 0 54 0 0
类别 参数 含义 说明
Procs r (Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。 当这个值超过了cpu个数,就会出现cpu瓶颈。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高
b 等待IO的进程数量,阻塞的进程
system in 每秒中断数,包括时钟中断 这两个值越大,会看到由内核消耗的cpu时间sy会越多这个值要越小越好,太大了,要考虑调低线程或者进程的数目
cs 每秒上下文切换数 同上,当进行线程的切换,进行上下文切换,这个值越小越好。
CPU us 用户进程执行消耗cpu时间 us的值比较高时,说明用户进程消耗的cpu时间多
sy 系统进程消耗cpu时间 sys的值过高时,说明系统内核消耗的cpu资源多,例如I/O频繁操作。
Id 空闲时间(包括IO等待时间) 一般来说 us+sy+id=100
wa 等待IO时间 wa过高时,说明io等待比较严重,可能由于磁盘大量随机访问造成,也有可能是磁盘的带宽出现瓶颈。
st 来自于虚拟机偷取的CPU所占的百分比
io bi 每秒从文件系统或SWAP读入到RAM(blocks in)的块数,block(1KB磁盘块)为单位 随机磁盘读写的时候,这2个值越大(如超出1024k),能看到CPU在IO等待的值也会越大。
bo 每秒从RAM写出到文件系统或SWAP(blocks out)的块数,block(1KB磁盘块)为单位
swap si 每秒从SWAP(交换分区)读入到RAM(swap in)的大小,单位是KB 内存够用的时候,这2个值都是0,如果这2个值长期大于0时,系统性能会受到影响。
so 每秒从RAM写出到SWAP(swap out)的大小,单位是KB
memory swpd 使用的虚拟内存的大小,单位是KB
free 可用的物理内存大小,单位是KB
buff 物理内存用来缓存读写操作的buffer大小,单位是KB
cache 物理内存用来缓存进程地址空间的cache大小,单位是KB

mpstat

(Multiprocessor Statistics)

功能:报告处理器相关的统计信息。

报告每个CPU的统计信息,-p ALL 用来打印CPU的报告,默认只打印系统级别的总结信息。

参数 解释
-P {|ALL} 表示监控哪个CPU,例如mpstat -P 0 mpstat -P 7 mpstat -P ALL
internal 相邻的两次采样的间隔时间
count 采样的次数,count只能和delay一起使用

各个字段含义

字段 含义
%usr 用户态占用CPU的时间(%),不包含nice值为正的进程时间,但包括了 guest 时间。
%nice 代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。这里注意,nice 可取值范围是 -20 到 19,数值越大,优先级反而越低。
%sys 内核态占用CPU的时间(%)
%iowait 等待IO占用CPU的时间(%)
%irq 硬中断占用CPU的时间(%)
%soft 软中断占用CPU的时间(%)
%guest CPU处理虚拟进程花费的时间开销
%idle 空闲CPU的时间(%)
%steal 代表当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间。

top

功能:显示最消耗CPU的任务,并且有百分百。

top的使用方式 top [-d number] | top [-bnp]

参数 含义
-d number number代表秒数,表示top命令显示的页面更新一次的间隔 (default=5s)
-b 以批次的方式执行top
-n 与-b配合使用,表示需要进行几次top命令的输出结果
-p 指定特定的pid进程号进行观察

top命令显示的页面还可以输入以下按键执行相应的功能(注意大小写区分的)

参数 含义
显示在top当中可以输入的命令
P 以CPU的使用资源排序显示
M 以内存的使用资源排序显示
N 以pid排序显示
T 由进程使用的时间累计排序显示
k 给某一个pid一个信号,可以用来杀死进程(9)
r 给某个pid重新定制一个nice值(即优先级)
q 退出top(用ctrl+c也可以退出top)

top各输出参数含义

image-20240516115231233

一、top前五条信息解释

top - 14:49:28 up 1:33, 1 user, load average: 0.00, 0.00, 0.00

内容 含义
14:49:28 表示当前时间
up 1:33 系统远行时间,格式为时:分
1 user 当前登陆用户数
load average: 0.00, 0.00, 0.00 系统负载,即任务队列的平均长度。 三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值

Tasks: 80 total, 2 running, 78 sleeping, 0 stopped, 0 zombie

内容 含义
Tasks: 80 total 进程总数
2 running 正在运行的进程数
78 sleeping 睡眠的进程数
0 stopped 停止的进程数
0 zombie 僵尸进程数

Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

内容 含义
0.0%us 用户空间占用CPU百分比
0.0%sy 内核空间占用CPU百分比
0.0%ni 用户进程空间内改变过优先级的进程占用CPU百分比
100.0%id 空闲CPU百分比
0.0%wa 等待输入输出的CPU时间百分比
0.0%hi 硬中断(Hardware IRQ)占用CPU的百分比
0.0%si 软中断(Software Interrupts)占用CPU的百分比
0.0 st 用于有虚拟cpu的情况,用来指示被虚拟机偷掉的cpu时间

Mem: 1922488k total, 406936k used, 1515552k free, 11940k buffers

内容 含义
1922488k total 物理内存总量
406936k used 使用的物理内存总量
1515552k free 空闲内存总量
11940k buffers 用作内核缓存的内存量

Swap: 835576k total, 0k used, 835576k free, 111596k cached

内容 含义
835576k total 交换区总量
0k used 使用的交换区总量
835576k free 空闲交换区总量
111596k cached 缓冲的交换区总量

二、进程信息

列名 含义
PID 进程id
USER 进程所有者的用户名
PR 优先级
NI nice值。负值表示高优先级,正值表示低优先级
VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
SHR 共享内存大小,单位kb
S 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
%CPU 上次更新到现在的CPU时间占用百分比
%MEM 进程使用的物理内存百分比
TIME+ 进程使用的CPU时间总计,单位1/100秒
COMMAND 命令名/命令行

Note:

  • VIRT 是进程虚拟内存的大小,只要是进程申请过的内存,即便还没有真正分配物理内存,也会计算在内。
  • RES 是常驻内存的大小,也就是进程实际使用的物理内存大小,但不包括 Swap 和共享内存。
  • SHR 是共享内存的大小,比如与其他进程共同使用的共享内存、加载的动态链接库以及程序的代码段等。
  • %MEM 是进程使用物理内存占系统总内存的百分比。

默认进入top时,各进程是按照CPU的占用量来排序的。

sar

文章:linux分析利刃之sar命令详解

功能:收集、报告或保存系统活动信息

sar是一个非常全面的一个分析工具,可以比较瑞士军刀,对文件的读写,系统调用的使用情况,磁盘IO,CPU相关使用情况,内存使用情况,进程活动等都可以进行有效的分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-A:所有报告的总和
-u:输出CPU使用情况的统计信息
-v:输出inode、文件和其他内核表的统计信息
-d:输出每一个块设备的活动信息
-r:输出内存和交换空间的统计信息
-b:显示I/O和传送速率的统计信息-R:输出内存页面的统计信息
-y:终端设备活动情况
-w:输出系统交换活动信息
-B:显示换页状态;
-e:设置显示报告的结束时间
-f:从指定文件提取报告
-i:设状态信息刷新的间隔时间
-p:报告每个CPU的状态
-q:平均负载分析

1.统计CPU使用情况

1
2
3
4
5
6
7
8
(base) sv@sv-NF5280M5:/home/sv$ sar -u 1 3# 统计CPU的使用情况,每间隔1秒钟统计一次总共统计三次
Linux 5.15.0-91-generic (sv-NF5280M5) 2024年05月16日 _x86_64_ (40 CPU)

15时00分10秒 CPU %user %nice %system %iowait %steal %idle
15时00分11秒 all 60.64 0.00 0.90 0.00 0.00 38.46
15时00分12秒 all 62.84 0.00 0.45 0.00 0.00 36.71
15时00分13秒 all 60.88 0.00 1.08 0.00 0.00 38.04
平均时间: all 61.46 0.00 0.81 0.00 0.00 37.73
1
2
3
4
5
6
7
8
9
(base) sv@sv-NF5280M5:/home/sv$ sar -o test.txt -u 1 3
(base) sv@sv-NF5280M5:/home/sv$ sar -u -f test.txt
Linux 5.15.0-91-generic (sv-NF5280M5) 2024年05月16日 _x86_64_ (40 CPU)

15时01分57秒 CPU %user %nice %system %iowait %steal %idle
15时01分58秒 all 61.59 0.00 0.43 0.00 0.00 37.99
15时01分59秒 all 66.08 1.00 0.93 0.00 0.00 31.99
15时02分00秒 all 62.38 0.10 1.13 0.00 0.00 36.39
平均时间: all 63.35 0.37 0.83 0.00 0.00 35.45

2.查看磁盘IO

查看I/O和传递速率的统计信息,每间隔1秒钟统计一次总共统计三次

1
2
3
4
5
6
7
8
(base) sv@sv-NF5280M5:/home/sv$ sar -b 1 3
Linux 5.15.0-91-generic (sv-NF5280M5) 2024年05月16日 _x86_64_ (40 CPU)

15时03分49秒 tps rtps wtps dtps bread/s bwrtn/s bdscd/s
15时03分50秒 0.00 0.00 0.00 0.00 0.00 0.00 0.00
15时03分51秒 0.00 0.00 0.00 0.00 0.00 0.00 0.00
15时03分52秒 2.00 0.00 2.00 0.00 0.00 24.00 0.00
平均时间: 0.67 0.00 0.67 0.00 0.00 8.00 0.00

pidstat

pidstat 是sysstat软件套件的一部分,sysstat包含很多监控linux系统状态的工具,它能够从大多数linux发行版的软件源中获得。

1
apt-get install sysstat

功能:pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。

按进程或线程打印CPU用量,包括用户态和系统态时间的分解。

cpu使用情况统计(-u),针对特定进程统计(-p)

  • UID:一列代表了进程的用户标识符(User Identifier)
  • PID: 进程pid
  • %usr: 进程在用户态运行所占cpu时间比率
  • %system: 进程在内核态运行所占cpu时间比率
  • %guest :任务花费在虚拟机上的cpu使用率(运行在虚拟处理器)
  • %CPU: 进程运行所占cpu时间比率
  • CPU: 指示进程在哪个核运行
  • Command: 拉起进程对应的命令
1
2
3
4
5
6
7
8
9
(base) sv@sv-NF5280M5:/home/sv$ pidstat
Linux 5.15.0-91-generic (sv-NF5280M5) 2024年05月16日 _x86_64_ (40 CPU)

15时08分27秒 UID PID %usr %system %guest %wait %CPU CPU Command
15时08分27秒 0 1 0.01 0.01 0.00 0.00 0.01 32 systemd
15时08分27秒 0 2 0.00 0.00 0.00 0.00 0.00 32 kthreadd
15时08分27秒 0 14 0.00 0.00 0.00 0.00 0.00 0 ksoftirqd/0
15时08分27秒 0 15 0.00 0.08 0.00 0.02 0.08 29 rcu_sched
...

分析CPU性能瓶颈方法

《速查表》

image-20240516151750649

通常先运行几个支持指标较多的工具,top,vmstat和pidstat

image-20240516152157984

  • 从 top 的输出可以得到各种 CPU 使用率以及僵尸进程和平均负载等信息。
  • 从 vmstat 的输出可以得到上下文切换次数、中断次数、运行状态和不可中断状态的进程数。
  • 从 pidstat 的输出可以得到进程的用户 CPU 使用率、系统 CPU 使用率、以及自愿上下文切换和非自愿上下文切换情况。

分析问题待填坑。

系统优化

  • CPU 绑定:一个进程可以被设置为只在一个或者多个特定的CPU上运行,而不是在所有的CPU上随机调度。这种技术被称为CPU亲和性(CPU Affinity)。通过设置CPU亲和性,可以提高缓存命中率和内存访问性能,从而提高整体性能。
  • CPU 独占:跟 CPU 绑定类似,进一步将 CPU 分组,并通过 CPU 亲和性机制为其分配进程。这样,这些 CPU 就由指定的进程独占,换句话说,不允许其他进程再来使用这些 CPU。
  • 优先级调整:使用 nice 调整进程的优先级,正值调低优先级,负值调高优先级
  • 为进程设置资源限制:使用 Linux cgroups 来设置进程的 CPU 使用上限,可以防止由于某个应用自身的问题,而耗尽系统资源。
  • NUMA(Non-Uniform Memory Access)优化:支持 NUMA 的处理器会被划分为多个 node,每个 node 都有自己的本地内存空间。NUMA 优化,其实就是让 CPU 尽可能只访问本地内存。
  • 中断负载均衡:无论是软中断还是硬中断,它们的中断处理程序都可能会耗费大量的 CPU。开启 irqbalance 服务或者配置 smp_affinity,就可以把中断处理过程自动负载均衡到多个 CPU 上。

内存篇

内存信息

查看内存信息命令

1
(base) sv@sv-NF5280M5:/home/sv$ cat /proc/meminfo

image-20240516163609218

查看红框信息

  • MemTotal:系统总内存,由于 BIOS、内核等会占用一些内存,所以这里和配置声称的内存会有一些出入,比如我这里配置有 2G,但其实只有 1.95G 可用。
  • MemFree:系统空闲内存。
  • MemAvailable:应用程序可用内存。有人会比较奇怪和 MemFree 的区别,可以从两个层面来区分,MemFree 是系统层面的,而 MemAvailable 是应用程序层面的。系统中有些内存虽然被使用了但是有一部分是可以回收的,比如 Buffers、Cached 及 Slab 这些内存,这部分可以回收的内存加上 MemFree 才是 MemAvailable 的内存值,这是内核通过特定算法算出来的,是一个估算值。
  • Buffers:缓冲区内存
  • Cached:缓存

常用命令

free

查看内存使用

1
2
3
4
5
6
7
8
(base) sv@sv-NF5280M5:/home/sv$ free
总计 已用 空闲 共享 缓冲/缓存 可用
内存: 65566072 34371864 6931596 927388 24262612 29574080
交换: 2097148 1718532 378616
(base) sv@sv-NF5280M5:/home/sv$ free -h
总计 已用 空闲 共享 缓冲/缓存 可用
内存: 62Gi 32Gi 6.6Gi 905Mi 23Gi 28Gi
交换: 2.0Gi 1.6Gi 369Mi

我们观察到free 很小,buff/cache 却很大。这是由于Linux设计思想:内存闲着反正也是闲着,不如拿出来做系统缓存和缓冲区,提高数据读写的速率。

  • Buffers 是内核缓冲区用到的内存,对应的是 /proc/meminfo 中的 Buffers 值。
  • Cache 是内核页缓存和 Slab 用到的内存,对应的是 /proc/meminfo 中的 Cached 与 SReclaimable 之和。

Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中

Swap

交换空间是硬盘上的一块区域,它被操作系统用作虚拟内存,用来在物理内存(RAM)不足时,存放暂时不需要的内存数据。

详细来说,当系统的物理内存不足以支持当前的所有进程时,操作系统会选择一些暂时不活跃的内存页,把它们从物理内存移动到交换空间,从而释放出物理内存给当前活跃的进程使用。这个过程被称为“交换出”(Swap Out)。

反过来,当这些被交换出的内存页再次被需要时,操作系统会把它们从交换空间移回到物理内存,这个过程被称为“交换入”(Swap In)。

pmap

这个命令用于查看进程的内存映像信息,能够查看进程在哪些地方用了多少内存。常用 pmap -x pid 来查看。

可以看到该进程内存被哪些库、哪些文件所占用,据此我们定位程序对内存的使用。

image-20240516164838320

几个字段介绍一下:

  • Address:占用内存的文件的内存起始地址。

  • Kbytes:占用内存的字节数。

  • RSS:实际占用内存大小。

  • Dirty:脏页大小。

  • Mapping:占用内存的文件,[anon] 为已分配的内存,[stack] 为程序堆栈

  • 最后的 total 为统计的总值。我们可以使用 pmap -x pid | tail -1 这样只显示最后一行,循环显示最后一行,达到监控该进程的目的。使用:

    while true; do pmap -x pid | tail -1; sleep 1; done

IO 篇

IO 和 存储密切相关,存储可以概括为磁盘,内存,缓存,三者读写的性能差距非常大,磁盘读写是毫秒级的(一般 0.1-10ms),内存读写是微妙级的(一般 0.1-10us),cache 是纳秒级的(一般 1-10ns)。

磁盘性能指标

五个常见指标

  • 使用率,是指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈。
  • 饱和度,是指磁盘处理 I/O 的繁忙程度。过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求。
  • IOPS(Input/Output Per Second),是指每秒的 I/O 请求数(每秒读写的次数)。
  • 吞吐量,是指每秒的 I/O 请求大小(每秒读写的数据量)。
  • 响应时间,是指 I/O 请求从发出到收到响应的间隔时间。

常用命令

fdisk

查看磁盘信息,包括磁盘容量,扇区大小,IO 大小等信息,常用 fdisk -l 查看:

1
2
3
4
5
6
(base) sv@sv-NF5280M5:/home/sv$ sudo fdisk -l
Disk /dev/loop0:63.97 MiB,67051520 字节,130960 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
...

df

查看磁盘使用情况,通常看磁盘使用率:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(base) sv@sv-NF5280M5:/home/sv$ df -h
文件系统 容量 已用 可用 已用% 挂载点
udev 32G 0 32G 0% /dev
tmpfs 6.3G 2.8M 6.3G 1% /run
/dev/sda2 439G 253G 164G 61% /
tmpfs 32G 136K 32G 1% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/loop1 128K 128K 0 100% /snap/bare/5
/dev/loop4 56M 56M 0 100% /snap/core18/2812
/dev/loop6 75M 75M 0 100% /snap/core22/1122
/dev/loop18 350M 350M 0 100% /snap/gnome-3-38-2004/140
/dev/loop17 13M 13M 0 100% /snap/snap-store/959
/dev/loop13 350M 350M 0 100% /snap/gnome-3-38-2004/143
/dev/loop19 92M 92M 0 100% /snap/gtk-common-themes/1535
/dev/loop14 219M 219M 0 100% /snap/gnome-3-34-1804/90
/dev/loop12 82M 82M 0 100% /snap/gtk-common-themes/1534
/dev/loop10 219M 219M 0 100% /snap/gnome-3-34-1804/93
/dev/sda1 511M 6.1M 505M 2% /boot/efi
/dev/sdb2 3.6T 438G 3.0T 13% /data
tmpfs 6.3G 76K 6.3G 1% /run/user/1000
...

vmstat

常用的还是这个万能的 vmstat:

1
2
3
4
(base) sv@sv-NF5280M5:/home/sv$ vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b 交换 空闲 缓冲 缓存 si so bi bo in cs us sy id wa st
24 0 1718020 6435840 450144 23930416 0 0 1 4 0 0 46 0 54 0 0

对于 IO,我们常关注三个部分:

  • b 值:表示因为 IO 阻塞排队的任务数
  • bi 和 bo 值:表示每秒读写磁盘的块数,bi(block in)是写磁盘,bo(block out)是读磁盘。
  • wa 值:表示因为 IO 等待(wait)而消耗的 CPU 比例。

一般这几个值偏大,都意味着系统 IO 的消耗较大,对于读请求较大的服务器,b、bo、wa 的值偏大,而写请求较大的服务器,b、bi、wa 的值偏大。

iostat

vmstat 虽然万能,但是它分析的东西有限,iostat 是专业分析 IO 性能的工具,可以方便查看 CPU、网卡、tty 设备、磁盘、CD-ROM 等等设备的信息,非常强大,总结下来,共有以下几种用法:

1)iostat -c 查看部分 CPU 使用情况:

1
2
3
4
5
(base) sv@sv-NF5280M5:/home/sv$ iostat -c
Linux 5.15.0-91-generic (sv-NF5280M5) 2024年05月16日 _x86_64_ (40 CPU)

avg-cpu: %user %nice %system %iowait %steal %idle
45.91 0.00 0.31 0.01 0.00 53.77

这里显示的是多个 CPU 的平均值,每个字段的含义我就不多解释了,我一般会重点关注 %iowait 和 %idle,分别表示 CPU 等待 IO 完成时间的百分比和 CPU 空闲时间百分比。

如果 %iowait 较高,则表明磁盘存在 IO 瓶颈,如果 %idle 较高,则 CPU 比较空闲,如果两个值都比较高,则有可能 CPU 在等待分配内存,瓶颈在内存,此时应该加大内存,如果 %idle 较低,则此时瓶颈在 CPU,应该增加 CPU 资源。

2)iostat -d 查看磁盘使用情况,主要是显示 IOPS 和吞吐量信息(-k : 以 KB 为单位显示,-m:以 M 为单位显示):

1
2
3
4
5
6
7
8
9
10
11
12
13
(base) sv@sv-NF5280M5:/home/sv$ iostat -d -k
Linux 5.15.0-91-generic (sv-NF5280M5) 2024年05月16日 _x86_64_ (40 CPU)

Device tps kB_read/s kB_wrtn/s kB_dscd/s kB_read kB_wrtn kB_dscd
loop0 0.00 0.00 0.00 0.00 731 0 0
loop1 0.00 0.00 0.00 0.00 21 0 0
loop10 0.00 0.00 0.00 0.00 2175 0 0
loop11 0.00 0.00 0.00 0.00 1460 0 0
loop12 0.00 0.00 0.00 0.00 2120 0 0
loop13 0.00 0.00 0.00 0.00 2192 0 0
loop14 0.00 0.00 0.00 0.00 2155 0 0
loop15 0.00 0.00 0.00 0.00 1234 0 0
loop16 0.00 0.00 0.00 0.00 1500 0 0

其中,几个参数分别解释如下:

  • tps:设备每秒的传输次数(transfers per second),也就是读写次数。
  • kB_read/s 和 kB_wrtn/s:每秒读写磁盘的数据量。
  • kB_read 和 kB_wrtn:读取磁盘的数据总量。

3)iostat -x 查看磁盘详细信息:

1
2
3
4
5
6
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
45.91 0.00 0.31 0.01 0.00 53.77

Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util
loop0 0.00 0.00 0.00 0.00 0.25 7.31 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
loop1 0.00 0.00 0.00 0.00 0.33 1.40 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

其中,几个参数解释如下;

  • rrqm/s 和 wrqm/s:分别每秒进行合并的读操作数和写操作数,这是什么意思呢,合并就是说把多次 IO 请求合并成少量的几次,这样可以减小 IO 开销,buffer 存在的意义就是为了解决这个问题的。
  • r/s 和 w/s:每秒磁盘读写的次数。这两个值相加就是 tps。
  • rkB/s 和 wkB/s:每秒磁盘读写的数据量,这两个值和上面的 kB_read/s、kB_wrnt/s 是一样的。
  • avgrq-sz:平均每次读写磁盘扇区的大小。
  • avgqu-sze:平均 IO 队列长度。队列长度越短越好。
  • await:平均每次磁盘读写的等待时间(ms)。
  • svctm:平均每次磁盘读写的服务时间(ms)。
  • %util:一秒钟有百分之多少的时间用于磁盘读写操作。

以上这些参数太多了,我们并不需要每个都关注,可以重点关注两个:

a. %util:衡量 IO 的繁忙程度

这个值越大,说明产生的 IO 请求较多,IO 压力较大,我们可以结合 %idle 参数来看,如果 %idle < 70% 就说明 IO 比较繁忙了。也可以结合 vmstat 的 b 参数(等待 IO 的进程数)和 wa 参数(IO 等待所占 CPU 时间百分比)来看,如果 wa > 30% 也说明 IO 较为繁忙。

b. await:衡量 IO 的响应速度

通俗理解,await 就像我们去医院看病排队等待的时间,这个值和医生的服务速度(svctm)和你前面排队的人数(avgqu-size)有关。如果 svctm 和 await 接近,说明磁盘 IO 响应时间较快,排队较少,如果 await 远大于 svctm,说明此时队列太长,响应较慢,这时可以考虑换性能更好的磁盘或升级 CPU。

4)iostat 1 2 默认显示 cpu 和 吞吐量信息,1 定时 1s 显示,2 显示 2 条信息

iotop

用于查看每个进程的 IO 情况,有了这个命令,就可以定位具体哪个进程的 IO 开销比较大了。

总结:fdisk -l 和 df 查看磁盘基本信息,iostat -d 查看磁盘 IOPS 和吞吐量,iostat -x 结合 vmstat 查看磁盘的繁忙程度和处理效率

网络篇

ping

ping 发送 ICMP echo 数据包来探测网络的连通性,除了能直观地看出网络的连通状况外,还能获得本次连接的往返时间(RTT 时间),丢包情况,以及访问的域名所对应的 IP 地址(使用 DNS 域名解析),比如:

1
2
3
4
5
6
7
8
9
10
(base) sv@sv-NF5280M5:/home/sv/pengeHome/webbench-c$ ping www.baidu.com
PING www.a.shifen.com (183.2.172.42) 56(84) bytes of data.
64 字节,来自 183.2.172.42 (183.2.172.42): icmp_seq=1 ttl=50 时间=32.9 毫秒
64 字节,来自 183.2.172.42 (183.2.172.42): icmp_seq=2 ttl=50 时间=32.7 毫秒
64 字节,来自 183.2.172.42 (183.2.172.42): icmp_seq=3 ttl=50 时间=32.9 毫秒
64 字节,来自 183.2.172.42 (183.2.172.42): icmp_seq=4 ttl=50 时间=32.8 毫秒
^C
--- www.a.shifen.com ping 统计 ---
已发送 4 个包, 已接收 4 个包, 0% 包丢失, 耗时 3004 毫秒
rtt min/avg/max/mdev = 32.677/32.833/32.946/0.103 ms

我们 ping baidu.com,-c 参数指定发包数。可以看到,解析到了 baidu 的一台服务器 IP 地址为 183.2.172.42。RTT 时间的最小、平均、最大和算术平均差分别是32.677/32.833/32.946/0.103 ms

ifconfig

ifconfig 命令被用于配置和显示 Linux 内核中网络接口的统计信息。通过这些统计信息,我们也能够进行一定的网络性能调优。

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
27
28
29
30
31
32
(base) sv@sv-NF5280M5:/home/sv/pengeHome/webbench-c$ ifconfig
eno1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether 9c:c2:c4:04:8a:78 txqueuelen 1000 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

eno2: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether 9c:c2:c4:04:8a:79 txqueuelen 1000 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

eno4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.168.157.251 netmask 255.255.255.0 broadcast 10.168.157.255
inet6 fe80::9ec2:c4ff:fe04:8a7b prefixlen 64 scopeid 0x20<link>
ether 9c:c2:c4:04:8a:7b txqueuelen 1000 (以太网)
RX packets 601118544 bytes 77263020820 (77.2 GB)
RX errors 0 dropped 56947 overruns 0 frame 0
TX packets 358969340 bytes 106533835973 (106.5 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (本地环回)
RX packets 250401850 bytes 62505601736 (62.5 GB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 250401850 bytes 62505601736 (62.5 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

这是关于Linux下的网络接口信息的输出。让我们逐行解释一下:

  1. eno4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500:这是网络接口eno4的状态信息。"UP"表示接口正在运行;"BROADCAST"表示接口有广播能力;"RUNNING"表示接口是活动的;"MULTICAST"表示接口支持多播。"mtu 1500"表示最大传输单元(MTU)是1500字节,这是以太网的标准MTU。
  2. inet 10.168.157.251 netmask 255.255.255.0 broadcast 10.168.157.255:这是IPv4的地址信息。"inet 10.168.157.251"表示IPv4地址是10.168.157.251;"netmask 255.255.255.0"表示子网掩码是255.255.255.0;"broadcast 10.168.157.255"表示广播地址是10.168.157.255。
  3. inet6 fe80::9ec2:c4ff:fe04:8a7b prefixlen 64 scopeid 0x20<link>:这是IPv6的地址信息。"inet6 fe80::9ec2:c4ff:fe04:8a7b"表示IPv6地址是fe80::9ec2:c4ff:fe04:8a7b;"prefixlen 64"表示前缀长度是64位;"scopeid 0x20< link >"表示这是一个链路本地地址。
  4. ether 9c:c2:c4:04:8a:7b txqueuelen 1000 (以太网):这是物理地址信息。"ether 9c:c2:c4:04:8a:7b"表示MAC地址是9c:c2:c4:04:8a:7b;"txqueuelen 1000"表示发送队列的长度是1000。
  5. RX packets 469211354 bytes 68619885994 (68.6 GB):这是接收(Receive)的数据信息。"RX packets 469211354"表示接收了469211354个数据包;"bytes 68619885994 (68.6 GB)"表示接收的数据总量是68.6 GB。
  6. TX packets 101656642 bytes 33416911871 (33.4 GB):这是发送(Transmit)的数据信息。"TX packets 101656642"表示发送了101656642个数据包;"bytes 33416911871 (33.4 GB)"表示发送的数据总量是33.4 GB。
  7. RX errors 0 dropped 56877 overruns 0 frame 0TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0:这些是网络错误的统计信息。包括错误的数据包数量、丢弃的数据包数量、overruns(数据包过多,接口处理不过来)的数量等。

IP

ip 命令用来显示或设置 Linux 主机的网络接口、路由、网络设备、策略路由和隧道等信息,是 Linux 下功能强大的网络配置工具,旨在替代 ifconfig 命令,如下显示 IP 命令的强大之处,功能涵盖到 ifconfig、netstat、route 三个命令。

image-20240521222605084

netstat

netstat 可以查看整个 Linux 系统关于网络的情况,是一个集多钟网络工具于一身的组合工具。
常用的选项包括以下几个:

  • 默认:列出连接的套接字
  • -a:列出所有套接字的信息
  • -s:各种网络协议栈统计信息
  • -i:网络接口信息
  • -r:列出路由表
  • -l:仅列出有在 Listen 的服务状态
  • -p:显示 PID 和进程名称

各参数组合使用实例如下:

  • netstat -at 列出所有 TCP 端口
  • netstat -au 列出所有 UDP 端口
  • netstat -lt 列出所有监听 TCP 端口的 socket
  • netstat -lu 列出所有监听 UDP 端口的 socket
  • netstat -lx 列出所有监听 UNIX 端口的 socket
  • netstat -ap | grep ssh 找出程序运行的端口
  • netstat -an | grep ‘:80’ 找出运行在指定端口的进程

1)netstat 默认显示连接的套接字数据

1
2
3
4
5
6
(base) sv@sv-NF5280M5:/home/sv/pengeHome/webbench-c$ netstat
激活Internet连接 (w/o 服务器)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 10.168.157.251:60242 182.100.46.118:https ESTABLISHED
tcp 1 0 10.168.157.251:33878 101.6.15.130:http CLOSE_WAIT
tcp 0 0 10.168.157.251:41326 182.100.46.63:https ESTABLISHED

2)netstat -i 显示网络接口信息

1
2
3
4
5
6
7
8
^C
(base) sv@sv-NF5280M5:/home/sv/pengeHome/webbench-c$ netstat -i
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eno1 1500 0 0 0 0 0 0 0 0 BMU
eno2 1500 0 0 0 0 0 0 0 0 BMU
eno4 1500 601157740 0 56947 0 358974952 0 0 0 BMRU
lo 65536 250402016 0 0 0 250402016 0 0 0 LRU

接口信息包括网络接口名称(Iface)、MTU,以及一系列接收(RX-)和传输(TX-)的指标。其中 OK 表示传输成功的包,ERR 是错误包,DRP 是丢包,OVR 是超限包。

这些参数有助于我们对网络收包情况进行分析,从而判断瓶颈所在。

3)netstat -s 显示所有网络协议栈的信息

4)netstat -r 显示路由表信息

1
2
3
4
5
6
(base) sv@sv-NF5280M5:/home/sv/pengeHome/webbench-c$ netstat -r
内核 IP 路由表
Destination Gateway Genmask Flags MSS Window irtt Iface
default 10.168.157.1 0.0.0.0 UG 0 0 0 eno4
10.168.157.0 0.0.0.0 255.255.255.0 U 0 0 0 eno4
link-local 0.0.0.0 255.255.0.0 U 0 0 0 eno4

ifstat

ifstat 主要用来监测主机网口的网络流量,常用的选项包括:

  • -a:监测主机所有网口
  • -i:指定要监测的网口
  • -t:在每行输出信息前加上时间戳
  • -b:以 Kbit/s 显示流量数据,而不是默认的 KB/s
  • -delay:采样间隔(单位是 s),即每隔 delay 的时间输出一次统计信息
  • -count:采样次数,即共输出 count 次统计信息

netcat

netcat,简称 nc,命令简单,但功能强大,在排查网络故障时非常有用,因此它也在众多网络工具中有着“瑞士军刀”的美誉。

它主要被用来构建网络连接。可以以客户端和服务端的方式运行,当以服务端方式运行时,它负责监听某个端口并接受客户端的连接,因此可以用它来调试客户端程序;当以客户端方式运行时,它负责向服务端发起连接并收发数据,因此也可以用它来调试服务端程序,此时它有点像 Telnet 程序。

常用的选项包括以下几种:

  • -l:以服务端的方式运行,监听指定的端口。默认是以客户端的方式运行。
  • -k:重复接受并处理某个端口上的所有连接,必须与 -l 一起使用。
  • -n:使用 IP 地址表示主机,而不是主机名,使用数字表示端口号,而不是服务名称。
  • -p:当以客户端运行时,指定端口号。
  • -s:设置本地主机发出的数据包的 IP 地址。
  • -C:将 CR 和 LF 两个字符作为结束符。
  • -U:使用 UNIX 本地域套接字通信。
  • -u:使用 UDP 协议通信,默认使用的是 TCP 协议。
  • -w:如果 nc 客户端在指定的时间内未检测到任何输入,则退出。
  • -X:当 nc 客户端与代理服务器通信时,该选项指定它们之间的通信协议,目前支持的代理协议包括 “4”(SOCKS v.4),“5”(SOCKS v.5)和 “connect” (HTTPs Proxy),默认使用 SOCKS v.5。
  • -x:指定目标代理服务器的 IP 地址和端口号。

下面举一个简单的例子,使用 nc 命令发送消息:

首先,启动服务端,用 nc -l 0.0.0.0 12345 监听端口 12345 上的所有连接。

1
2
3
(base) sv@sv-NF5280M5:/home/sv$ nc -l 127.0.0.1 12345
Hello
World

然后,启动客户端,用 nc -p 1234 127.0.0.1 12345 使用 1234 端口连接服务器 127.0.0.1::12345。

1
2
3
(base) sv@sv-NF5280M5:/home/sv$ nc -p 1234 127.0.0.1 12345
Hello
World

着就可以在两端互发数据了。

tcpdump

最后是 tcpdump,强大的网络抓包工具。虽然有 wireshark 这样更易使用的图形化抓包工具,但 tcpdump 仍然是网络排错的必备利器。

tcpdump 选项很多,我就不一一列举了,大家可以看文章末尾的引用来进一步了解。这里列举几种 tcpdump 常用的用法。

1)捕获某主机的数据包

比如想要捕获主机 200.200.200.100 上所有收到和发出的所有数据包,使用:

1
tcpdump host 200.200.200.100

2)捕获多个主机的数据包

比如要捕获主机 200.200.200.1 和主机 200.200.200.2 或 200.200.200.3 的通信,使用:

1
tcpdump host 200.200.200.1 and \(200.200.200.2 or \)

同样要捕获主机 200.200.200.1 除了和主机 200.200.200.2 之外所有主机通信的 IP 包。使用:

1
tcpdump ip host 200.200.200.1 and ! 200.200.200.2

3)捕获某主机接收或发出的某种协议类型的包

比如要捕获主机 200.200.200.1 接收或发出的 Telnet 包,使用:

1
tcpdump tcp port 23 host 200.200.200.1

4)捕获某端口相关的数据包

比如捕获在端口 6666 上通过的包,使用:

1
tcpdump port 6666

5)捕获某网口的数据包

比如捕获在网口 eth0 上通过的包,使用:

1
tcpdump -i eth0

面试题目

Pro1:CPU 飙高 100%怎么排查

学习自:面试官:在开发过程中遇到过 CPU 100% 的情况吗?怎么排查的?

整体思路:

  • 首先使用 top -c 找到 CPU 占用最高的进程;
  • 然后使用 top -Hp PID 找到进程下 CPU 占用最高的线程 PID,并且将十进制 PID 转换成十六进制;
  • 之后使用 jstack 命令导出进程快照;
  • 最后用 cat 命令结合 grep 命令对十六进制线程 PID 进行过滤,可以定位到出现问题的代码。

详细过程

1)找到 CPU 占用最高的进程

  • 使用top -c命令得到进程运行列表,然后按P按照 CPU 占用率排序;
  • 得到排在第一的进程的 PID:18412

image-20240630160714556

2)找到 CPU 占用最高的线程

  • 使用top -Hp 18412命令得到这个进程下的线程列表,然后按P按照 CPU 占用率排序;
  • 得到排在第一的线程的 PID:18413

image-20240630160742794

将十进制 PID 转换为十六进制得到47ED

3)导出进程快照并定位问题

  • 使用jstack命令导出进程快照;
1
jstack -l 18412 > ./18412.stack
  • 根据第二部得到的小写的十六进制线程 PID 使用 grep 命令进行查找;
1
cat 18412.stack | grep '47ed' -C 8
  • 从查询得到的堆栈信息中即可定位到有问题的代码;

image-20240630160818325

参考资料: