我们不能失去信仰

我们在这个世界上不停地奔跑...

0%

Linux性能指标之CPU

CPU

1
2
3
4
5
6
➜  ~ uptime
10:57:12 // 当前时间
up 25 days, 14:38, //系统运行时间
2 users, // 正在登录用户数
load average: 1.03, 0.58, 0.43 // 平均负载
➜ ~

上面是哪个数字分别表示 1分钟、 5分钟、 15分钟的平均负载。

  • 平均负载:单位时间内,系统处于可运行和不可中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。
    • 可运行状态: 指正在使用CPU或者正在等待CPU的进程,也就是 ps 命令看到 处于 R (Running 或 Runnable) 的进程。
    • 不可中断:进程处于内核态关键流程中的进程,这些进程不可打断,常见于等待硬件设备的 I/O响应,ps中的 D 状态 (Uninterruptible Sleep, 也称为 Disk Sleep) 的进程。这种状态实际上是系统对进程和硬件设备的一种保护机制。

理想状态下:每个CPU 刚好运行一个进程,平均负载是2 的时候。

1个CPU: 意味着有一半的进程竞争不到 CPU

2 个 CPU: 意味着 CPU 刚好被完全占用

4 个 CPU: 意味着 CPU 有 50% 空闲

平均负载最理想的情况是等于 CPU 个数。

查看 CPU 命令:

1
2
3
4
5
grep 'model name' /proc/cpuinfo | wc -l
4
// 输出的 cpu 数量为 4
或者通过
lscpu

1 分钟、 5分钟、15 分钟 负载并不是单独参考某一个,而是都要看,如果 1分钟的负载小,而 5 分钟的负载大,说明负载在下降, 如果 1分钟的负载大,5分钟的负载小,说明负载在上升。

当平均负载高于 CPU 数量 70%(这个数值因具体环境而定) 的时候,如4个CPU,平均负载为 7 的时候就需要注意了。

平均负载与 CPU 使用率的关系

平均负载包含等待CPU和等待 I/O 的进程。而 CPU 使用率,是单位时间内 CPU 繁忙情况统计,只包含了正在使用 CPU 的时间。

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

实践

安装 stress、sysstat, stress 是一个Linux 系统压力测试工具、sysstat 会包含两个命令 mpstat 和 pidstat

  • mpstat 是一个常用的多核 CPU 性能分析工具,用来实时查看每个 CPU 的性能指标,以及所有 CPU 的平均指标。
  • pidstat 是一个常用的进程性能分析工具,用来实时查看进程的 CPU、内存、I/O 以及上下文切换等性能指标。
1
2
3
4
5
6
7
8
9
10
11
# stress --cpu 1 --timeout 600 // 模拟 CPU密集型任务
# watch -d uptime
# mpstat -P ALL 5 // -P ALL 表示监控所有 CPU,后面数字 5 表示间隔 5 秒后输出一组数据

# pidstat -u 5 1 // 间隔 5 秒后输出一组数据

// 测试 io 密集型
# stress -i 1 --timeout 600

// 大量进程的场景
# stress -c 8 --timeout 600 /// 模拟 8个进程

CPU 上下文切换影响负载

进程竞争 CPU 的时候,并没有真正执行,为什么还会导致PCU负载上升,因为 CPU 会发生上下文切换。根据任务的不同,CPU上下文切换分为几个不同场景:

根据一份测试报告,每次上下文切换都需要几十纳秒到数微秒的时间。

  • 一次系统调用,其实是发生了两次 CPU 上下文切换,从用户态到内核态,再从内核态到用户态。 这是在同一个进程上面切换的,系统调用过程通常称为 特权模式切换,而不是上下文切换。

定位耗时代码

1
2
3
4
5
6
# apt install linux-perf && sysstat

# -g 开启调用关系分析,-p 指定 php-fpm 的进程号 21515
# perf top -g -p 21515
寻找调用关系,然后 查看源码
# grep xxx -r app/

总结: 使用top 、vmstat、pidstat 排查高 CPU 使用率的进程,然后再使用 perf top 工具,定位应用内部函数问题。

CPU 很高,但是找不到高 CPU的应用

在一些进程是短进程的时候,很难用 top 这种间隔时间比较长的工具发现。

如果对某些进程有疑问,可以先使用 pstree 找到其父进程,然后分析

1
# pstree | grep nginx

寻找这种问题最好的办法是:

1
2
3
4
5
6
7
8
9
10
# 记录性能时间,等待大约15秒后退出
# perf record -g

# 查看报告
# perf report
# perf record -ag -- sleep 2;perf report // 上面两句话合二为一

# 或者使用 execsnoop

# execsnoop // 是一个转为短时进程设计的工具。它通过 ftrace 实时监控进程的 exec() 行为,并输出短时进程的基本信息,包括进程PID、父进程PID、命令行参数及执行的结果。

总结: 如果碰到 CPU 使用率很高,但是又找不到是哪个进程,可以看看某个应用程序是否调用了其他而进程程序失败,导致不停的崩溃重启,而启动过程的资源初始化,很可能会占用相当多的CPU。

进程的几个状态

top中进程的状态:

  • R:Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行

  • D:Disk Sleep,也就是不可中断状态睡眠,一般表示进程正在跟硬件交互,并且交互过程中不允许被其他进程或中断打断。

  • Z: Zombie, 僵尸进程,实际上进程已经结束,但是父进程没有回收它的资源(比如进程的描述符、PID 等)

  • S: Interruptible Sleep, 也就是中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事情发生时,它会被唤醒并进入 R 状态。

  • I: Idle ,空闲状态,用在不可中断睡眠的内核线程上。对某些内核线程来说,他们可能实际上并没有任何负载,用Idle 正是为了区分这种情况。D状态会导致平均升高,I状态的进程却不会。

  • T/t: Stopped 或 Traced,表示进程处于暂停或者跟踪状态

    向一个进程发送 SIGSTOP 信号,他就会响应这个信号,变成暂停状态;在向他发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要用fg命令恢复到前台运行。) 当使用调试器如gdb进行调试的时候,在使用断点中断进程后,就是 t 状态。

  • X: Dead 的缩写,表示进程已消亡,所以不会在top 或者ps 中看到它。

僵尸进程如果其父进程一直没有回收它,父进程挂了后,由 init 进行回收。

工具:

1
2
3
4
5
6
# dstat // 可以同时查看 cpu 和 io

# -a 表示输出命令行选项
# p 表 PID
# s 表示指定进程的父进程
$ pstree -aps 3084

软中断

中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的终端处理程序来响应设备的请求。

中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力。

由于终端处理程序会打断其他进程的运行,所以,为了减少对正常进程运行调度的影响,终端处理程序就需要尽可能快地运行。如果中断本身要做的事情不多,那么处理起来也不会有太大的问题;但是如果中断要处理的事情很多,中断服务程序就有可能要运行很长时间。

因为中断处理程序在响应中断时,还会临时关闭中断。就会导致在这段时间内可能会丢失中断,所以操作系统将中断处理程序执行过长和中断丢失的问题分成了两个阶段, 上半部和下半部。

上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作

下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行。

如: 网卡接收到数据包后,会通过硬中断通知内核处理, 对于上半部分来说就是把网卡数据更新到内存,然后更新硬件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理。

而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,然后发送给应用程序。

总结:

  • 上半部分直接处理硬件请求,也就是我们常说的硬中断, 特点是快速执行
  • 下半部分则是由内核触发,也就是我们常说的软中断,特点是延迟执行,异步处理完成上半部分未完成的工作
  • 软中断以内核线程方式执行,并且每个CPU都对应一个软中断内核线程,名字为“ksoftirqd/CPU编号”。
1
2
3
4
5
# cat /proc/softirqs   // 查看软中断

# cat /proc/interrupts // 提供了硬中断的运行情况。

# ps aux | grep softirq

探究软中断

  • sar 是一个系统活动报告工具,既可以实时查看系统的当前活动,又可以配置保存和报告历史统计数据。
  • hping3 是一个可以构造 TCP/IP 协议数据包的工具,可以对系统进行安全审计、防火墙测试等。
  • tcpdump 是一个常用的网络抓包工具,常用来分析各种网络问题。

新工具:

1
2
3
4
# -S 参数表示设置 TCP 协议的 SYN(同步序列号),-p 表示目的端口为 80
# -i u100 表示每隔 100 微秒发送一个网络帧
# 注:如果你在实践过程中现象不明显,可以尝试把 100 调小,比如调成 10 甚至 1
$ hping3 -S -p 80 -i u100 192.168.0.30

使用上面的命令发送 SYN FLOOD 攻击, 会发送很多帧,每帧都很小,发生 SYN FLOOD 攻击,让服务器一直处在中断切换之间,从而造成 CPU 升高。