分析决策树中
image.png

操作系统模块
image.png

监控命令

常用的监控命令有很多, 如下
image.png
image.png

只需要记住关键4个, 以下是模块与命令的对应关系, 且注意思路为, 你要监控 CPU 的某个计数器才执行了这个命令,而不是因为自己知道这个命令才去执行。
image.png
image.png

监控平台 Grafana+Prometheus+node_exporter

略..先全局监控再定向监控, 这里是全局监控

CPU

CPU常见的计数器是top中的8个值

  • us, 用户空间占用CPU百分比
  • sy, 内核空间占用CPU百分比
  • ni, 用户空间内改变过优先级的进程占用CPU百分比
  • id, 空间CPU百分比
  • wa, 等待输入输出CPU时间百分比
  • hi, CPU服务于硬件中断所耗费的时间总额
  • si, CPU服务软件中断所耗费的时间总额
  • st, Steal Time ```shell root@DESKTOP-LMORNNS:~# top

当前系统时间 系统到现在已运行的时间, 当前登录系统的用户数量, 系统负载(任务队列的平均长度, 3个值分别为1min, 5min, 15min到现在的平均值, 一般小于1)

top - 20:08:58 up 0 min, 0 users, load average: 0.09, 0.03, 0.01

所有启动的进程数, 正在运行的进程数, 挂起的进程数, 停止的进程数, 僵尸进程数

Tasks: 5 total, 1 running, 4 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.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

物理内存总量, 空闲物理内存, 已使用的物理内存, 内核缓存内存量

MiB Mem : 12704.5 total, 12514.4 free, 82.9 used, 107.3 buff/cache

交换区总量, 空间交换区总量, 已使用的交换区总量, 缓冲交换区总量

MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 12420.1 avail Mem

进程ID 进程所有者 优先级 nice值(负值表示高优先级, 正值表示低优先级)

  1. #进程使用的虚拟内存总量
  2. # #进程使用的, 未被换出的物理内存大小
  3. # # #共享内存大小
  4. # # # #进程状态
  5. # # # # #上次更新到现在的CPU时间占用百分比
  6. # # # # # #进程使用的物理内存百分比
  7. # # # # # # #进程使用CPU总时间
  8. # # # # # # # #命令名, 命令行

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 896 524 464 S 0.0 0.0 0:00.02 init 10 root 20 0 896 80 20 S 0.0 0.0 0:00.00 init 11 root 20 0 896 80 20 S 0.0 0.0 0:00.00 init 12 root 20 0 15016 4992 3300 S 0.0 0.0 0:00.03 bash 120 root 20 0 15848 3696 3184 R 0.0 0.0 0:00.00 top

  1. 常见问题大部分体现在以下计数器上: us, wa, sy, si
  2. <a name="c21bt"></a>
  3. ### us
  4. usCPU用户态进程消耗的CPU百分比, 定向分析的链条如下<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/281275/1653308708219-59ca6312-3724-4267-89e5-bf985d9023c2.png#clientId=u833365b3-09d8-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u252b64a2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1216&originWidth=1592&originalType=url&ratio=1&rotation=0&showTitle=false&size=249815&status=done&style=none&taskId=ub920816e-e868-4cba-b7fa-8950fc3759d&title=)
  5. ```shell
  6. # 找出CPU占比最高的进程PID(先top, 再shift+p按照CPU使用率排序)
  7. top
  8. # 找到进程中消耗资源最高的线程TID
  9. top -H -p [PID]
  10. # 将线程id转为16进制
  11. printf "%x\n" [TID]
  12. # 打印线程快照
  13. jstack [PID] |grep [16进制的TID] -A 30

wa

wa是I/O读写等待消耗的CPU百分比, 分析链条如下
image.png

  1. iotop直接跳到对应的线程
  2. -P 也可以看到进程(shift+p能互相转换)

sy

sy是内核消耗的CPU百分比, 分析链路如下
image.png

如果我们看到一个系统的进程消耗了更多的资源,那就要去查一下这个进程是干吗的,看它的运行逻辑和配置文件。不一定所有情况都是配置的问题,但绝大多数情况是这个原因,只能说,在系统级别,我们遇到的内核进程本身有性能问题的情况还是很少的。大部分时候都只是配置问题。

si

si是软中断消耗的CPU百分比

简单点来说,当出现异常或资源争用时,它是用来管理秩序的。CPU 正在吭哧吭哧着干活呢,突然来了一个优先级高的,needs immediate attention,这时就会发一个中断信号给 CPU。作为一个干活的,CPU 谁的话都得听,这时候就把手头的工作现场保存一下,干这个优先级高的活。除非这个中断是致命的,不然 CPU 会在干完这个活之后再回去干之前的活,这就是一次软中断。

image.png

在这个判断的链路中,就是要把 si 的中断模块找出来,然后再分析这个模块的功能和配置。比如我们看网卡的中断,这是常见的一种性能问题。我们要知道网络是带宽不够?还是配置得不对?还是防火墙?还是啥啥啥别的原因?

老师,1. 在落地si cpu 的时候 看interrupts的目的是什么,不能直接看softirqs吗 ?从interrupts—>softirqs 这个判断逻辑是什么? 2. 判断si 高低的逻辑和标准是什么? 作者回复: 1. 看interrupts是为了对应中断号和设备名。看softirqs是为了看模块名。从interrupts—>softirqs 是相同的数据,不需要判断呀。 2. SI高低没有标准。主要看它对性能产生了多大的影响。

其他

ni 呢,在我职业生涯中就没见过它高过;hi 倒是见过,不过是因为硬件坏了;st 呢,只有无良商家不断超卖虚拟服务器才会出现。如果你在一个企业内部搭建的虚拟化基础平台上也经常看见这种情况,那就是公司太穷了,硬件都不够用。

swap是干嘛的?

在Linux下,SWAP的作用类似Windows系统下的“虚拟内存”。当物理内存不足时,拿出部分硬盘空间当SWAP分区(虚拟成内存)使用,从而解决内存容量不足的情况。 SWAP意思是交换,顾名思义,当某进程向OS请求内存发现不足时,OS会把内存中暂时不用的数据交换出去,放在SWAP分区中,这个过程称为SWAP OUT。当某进程又需要这些数据且OS发现还有空闲物理内存时,又会把SWAP分区中的数据交换回物理内存中,这个过程称为SWAP IN。 当然,swap大小是有上限的,一旦swap使用完,操作系统会触发OOM-Killer机制,把消耗内存最多的进程kill掉以释放内存。

还有一点要注意,soft faults会不断增加。

I/O

当一个系统调到非常精致的程度时,基本上会卡在两个环节上,对计算密集型的应用来说,会卡在 CPU 上;对 I/O 密集型的应用来说,瓶颈会卡在 I/O 上。

简化的I/O逻辑过程
image.png

iostat

image.png
从上图中取1条如下

  1. Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz
  2. vda 0.00 0.67 18.33 114.33 540.00 54073.33 823.32
  3. avgqu-sz await r_await w_await svctm %util
  4. 127.01 776.75 1.76 901.01 7.54 100.00
  5. # svctm 代表 I/O 平均响应时间, 但后续会废弃, 不可信, 因此不要看
  6. # w_await表示写入的平均响应时间
  7. # r_await表示读取的平均响应时间
  8. # r/s表示每秒读取次数
  9. # w/s表示每秒写入次数
  10. IO/s的关键计算如下
  11. # 每秒的IO数量为读+写
  12. IO/s = r/s + w/s = 18.33+114.33 = 132.66
  13. # IO使用率=((IO/s*响应时间(ms))/1000ms) * 100%
  14. # 因为使用svctm计算, 只能做参考
  15. %util = ( (IO/s * svctm) /1000) * 100% = 100.02564%

iotop

可以直接看到哪个线程占的I/O高

  1. Total DISK READ : 2.27 M/s | Total DISK WRITE : 574.86 M/s
  2. Actual DISK READ: 3.86 M/s | Actual DISK WRITE: 34.13 M/s
  3. TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
  4. 394 be/3 root 0.00 B/s 441.15 M/s 0.00 % 85.47 % [jbd2/vda1-8]
  5. 32616 be/4 root 1984.69 K/s 3.40 K/s 0.00 % 42.89 % kube-controllers
  6. 13787 be/4 root 0.00 B/s 0.00 B/s 0.00 % 35.41 % [kworker/u4:1]
  7. ...............................
  8. # Total 的值显示的是用户态进程与内核态进程之间的速度
  9. # Actual 显示的是内核块设备子系统与硬件之间的速度
  10. 而在I/O交互中,由于存在cache和在内核中会做I/O排序,因此这两个值并不会相同。
  11. 那如果你要说磁盘的读写能力怎么样,我们应该看的是Actual。这个没啥好说的,因为Total再大,不能真实写到硬盘上也是没用的。

Memory

一般只看业务系统即可

  1. [root@7dgroup ~]# free -m
  2. total used free shared buff/cache available
  3. Mem: 3791 1873 421 174 1495 1512
  4. Swap: 0 0 0
  5. # available,这个值才是系统真正可用的内存,而不是free。
  6. 因为 Linux 通常都会把用的内存给cache,但是不一定会用,所以free肯定会越来越少,但是available是计算了buffcache中不用的内存的,所以只要available多,就表示内存够用。

当出现内存泄露或因其他原因导致物理内存不够用的时候,操作系统就会调用OOM Killer,这个进程会强制杀死消耗内存大的应用。这个过程是不商量的,然后你在“dmesg”中就会看到如下信息

  1. [12766211.187745] Out of memory: Kill process 32188 (java) score 177 or sacrifice child
  2. [12766211.190964] Killed process 32188 (java) total-vm:5861784kB, anon-rss:1416044kB, file-rss:0kB, shmem-rss:0kB

这种情况只要出现,TPS 肯定会掉下来,如果你有负载均衡的话,压力工具中的事务还是可能有成功的。但如果你只有一个应用节点,或者所有应用节点都被OOM Killer给干掉了,那 TPS 就会是这样的结果。
image.png
对内存监控,可以看到这样的趋势:
image.png
内存慢慢被耗光,但是杀掉应用进程之后,free内存立即就有了。你看上面这个图,就是一个机器上有两个节点,先被杀了一个,另一个接着泄露,又把内存耗光了,于是又被杀掉,最后内存全都空闲了
对这种情况的分析定位,只看物理内存已经没有意义了,更重要的是看应用的内存是如何被消耗光的。对于内存的分析,你还可以用nmon和cat/proc/meminfo看到更多信息
如果你的应用是需要大页处理的,特别是大数据类的应用,需要关注HugePages相关的计数器

网络

分析链如下
image.png

网络IO栈如下:

  • 数据发送过程, 应用把数据给到tcp_wmem就结束它的工作了,由内核接过来之后,经过传输层,再经过队列、环形缓冲区,最后通过网卡发出去。
  • 数据接收过程, 网卡把数据接过来,经过队列、环形缓冲区,再经过传输层,最后通过tcp_rmem给到应用。

image.png

Recv_Q 和 Send_Q

通过netstat或其他命令可以看到Recv_Q和Send_Q,这两项至少可以告诉你瓶颈会在哪一端
image.png

  • 优先看Recv_Q, 当某一端Recv_Q有值而Send_Q无值时, 即表示请求挤压, 这一端有问题
  • 再看Send_Q, 当Send_Q有值而接收端Recv_Q无值时, 即表示发送端或是网络设备有问题

image.png

三次握手和四次挥手

握手

image.png
主要看这里面的两个队列:半连接队列和全连接队列。在 B 只接到第一个syn包的时候,把这个连接放到半连接队列中,当接到ack的时候才放到全连接队列中。这两个队列如果有问题,都到不了发送接收数据的时候,你就看到报错了

查看半连接全连接溢出的手段也很简单,像下面这种情况就是半连接没建立起来,半连接队列满了,syn包都被扔掉了。

  1. [root@7dgroup ~]# netstat -s |grep -i listen
  2. 8866 SYNs to LISTEN sockets dropped

那么半连接队列和什么参数有关呢?

  1. 代码中的backlog:你是不是想起来了ServerSocket(int port, int backlog)中的backlog?是的,它就是半连接的队列长度,如果它不够了,就会丢掉syn包了。
  2. 还有操作系统的内核参数net.ipv4.tcp_max_syn_backlog。

而像下面这样的情况呢,就是全连接队列已经满了,但是还有连接要进来,已经超过负荷了。

  1. [root@7dgroup2 ~]# netstat -s |grep overflow
  2. 154864 times the listen queue of a socket overflowed

这是在性能分析过程中经常遇到的连接出各种错的原因之一,它和哪些参数有关呢?我列在这里。

  1. net.core.somaxconn:系统中每一个端口最大的监听队列的长度
  2. net.core.netdev_max_backlog:每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目。
  3. open_file:文件句柄数。

挥手

image.png
在挥手的逻辑中,和性能相关的问题真的非常少

  • 我遇到性能测试过程中的挥手问题,有很多都是做性能分析的人在不了解的情况下就去做各种优化动作而产生的
  • 在我的性能工作经验中,只有一种情况要处理TIME_WAIT,那就是端口不够用的时候

    TCP/IPv4的标准中,端口最大是 65535,还有一些被用了的,所以当我们做压力测试的时候,有些应用由于响应时间非常快,端口就会不够用,这时我们去处理TIME_WAIT的端口,让它复用或尽快释放掉,以支持更多的压力。

  • 所以处理TIME_WAIT的端口要先判断清楚,如果是其他原因导致的,即使你处理了TIME_WAIT,也没有提升性能的希望。

System

最常见的 System 的计数器是in(interrupts:中断)和cs(context switch:上下文切换)。

  • in见上文
  • cs, 注意不止中断, 多任务处理也会导致cs, cs是被动的, 这个值的高或低都不会是问题的原因, 只会是一种表现, 因此它只能用来做性能分析中的证据链

Swap

Swap 的逻辑是什么呢?它是在磁盘上创建的一个空间,当物理内存不够的时候,可以保存物理内存里的数据。如下图所示:
image.png

  • 和 Swap 相关的计数器有:top中的Total、free、used和vmstat里的si、so。
  • 说到 Swap,在性能测试和分析中,我的建议是直接把它关了。为什么呢?因为当物理内存不足的时候,不管怎么交换性能都是会下降的,不管是 Swap 还是磁盘上的其他空间,都是从磁盘上取数据,性能肯定会刷刷往下掉。
  • 想关掉 Swap 就swapoff -a。

总结

  1. 监控平台再花哨,都只是提供数据来给你分析的。只要知道了数据的来源、原理、含义,用什么工具都不重要。
  2. 性能分析的时候,不会只看操作系统一个模块或哪几个固定计数器的。这些动态的数据,需要有分析链把它们串起来。
  3. 操作系统提供的监控数据是分析链路中不可缺少的一环,除非你能绕过操作系统,又能很确切地定位出根本原因。