前言:为了更好配置分布式储存集群的运行参数,使用性能分析工具观察业务环境是一种必要的手段
op 或者 uptime
02:34:03 //当前时间 up 2 days, 20:14 //系统运行时间 1 user //正在登录用户数 load average: 0.63, 0.83, 0.88 依次则是过去 1 分钟、5 分钟、15 分钟的平均负载(Load Average)
平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系,所以,它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。
可运行状态
可运行状态的进程,是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程
可中断的睡眠状态的进程会睡眠直到某个条件变为真,如产生一个硬件中断、释放进程正在等待的系统资源或是传递一个信号都可以是唤醒进程的条件。
不可中断状态
不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的
那就是把信号传递到这种睡眠状态的进程不能改变它的状态,也就是说它不响应信号的唤醒。
比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程被打断了,就容易出现磁盘数据与进程数据不一致的问题。所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制。
既然平均的是活跃进程数,那么最理想的,就是每个 CPU 上都刚好运行着一个进程,这样每个 CPU 都得到了充分利用。
比如当平均负载为 2 时,意味着什么呢?
1.在只有 2 个 CPU 的系统上,意味着所有的 CPU 都刚好被完全占用。
2.在 4 个 CPU 的系统上,意味着 CPU 有 50% 的空闲。
3.而在只有 1 个 CPU 的系统中,则意味着有一半的进程竞争不到 CPU。 ====》 (平均负载比cpu个数大,过载 )
所以 平均负载最理想的情况是等于 CPU 个数
grep 'model name' /proc/cpuinfo | wc -l //可查看cpu数目 12 //12核
如何观察数值
//假设单核情况 root@xxxx:~# uptime 09:28:31 up 1 day, 10:31, 2 users, load average: 1.96, 1.29, 1.59
假设是单核情况下, 1分钟下来有96%超载,5分钟下来有29%超载,15分钟下来有59%超载
1.当三者相差不大,说明系统的平均负载稳定。
2.当前1分钟比后两者小的时候,说明系统趋于降低
3.如果1分钟的值远大于 15 分钟的值,就说明最近 1 分钟的负载在增加
经验值之谈,一旦平均负载达到CPU数量的前后 75%左右,需要排查负载高的问题。
平均负载与 CPU 使用率区别
CPU 使用率,是单位时间内 CPU 繁忙情况的统计,跟平均负载并不一定完全对应
CPU使用率:单位时间内cpu繁忙情况的统计
情况1:CPU密集型进程,CPU使用率和平均负载基本一致
情况2:IO密集型进程,平均负载升高,CPU使用率不一定升高
情况3:大量等待CPU的进程调度,平均负载升高,CPU使用率也升高
场景模拟
借用iostat mpstat pidstat可以分析出平均负载升高的原因。
模拟一下使用场景
root@xxxx:~# apt install sysstat //常用的 Linux 性能工具,用来监控和分析系统的性能,包含两个命令 mpstat 和 pidsta root@xxxx:~# apt install stress //一个 Linux 系统压力测试工具
前提环境:
机器配置:4 CPU,8GB 内存。
root@xxxx:~# uptime 11:36:37 up 13 days, 29 min, 3 users, load average: 0.06, 0.06, 0.01
CPU 的用户层(%usr)使用率;
CPU 的系统层(%sys)使用率;
CPU 的 I/0 - 等待(%iowait);
CPU 的空闲率(%idle);
首先,我们在第一个终端运行 stress 命令,模拟一个 CPU 使用率 100% 的CPU 密集型进程场景:
//一终端执行 root@xxxx:~# stress --cpu 4 --timeout 555 stress: info: [4563] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd //另一终端 root@xxxx:~# watch -d uptime Every 2.0s: uptime xxxx: Tue Dec 22 11:43:36 2020 11:43:36 up 13 days, 36 min, 3 users, load average: 4.13, 1.28, 0.46 // 另一终端2 //-P ALL 表示监控所有CPU,后面数字5表示间隔5秒后输出一组数据 root@xxxx:~# mpstat -P ALL 5 11:45:26 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 11:45:31 AM all 99.65 0.00 0.25 0.00 0.00 0.10 0.00 0.00 0.00 0.00 11:45:31 AM 0 99.40 0.00 0.40 0.00 0.00 0.20 0.00 0.00 0.00 0.00 11:45:31 AM 1 99.60 0.00 0.40 0.00 0.00 0.00 0.00 0.00 0.00 0.00 11:45:31 AM 2 99.80 0.00 0.20 0.00 0.00 0.00 0.00 0.00 0.00 0.00 11:45:31 AM 3 99.80 0.00 0.00 0.00 0.00 0.20 0.00 0.00 0.00 0.00 //从这里可以明显看到,stress 进程的 CPU 使用率接近 100%。 root@xxxx:~# pidstat -u 5 1 Linux 4.15.0-66-generic (xxxx) 12/22/2020 _x86_64_ (4 CPU) 11:48:58 AM UID PID %usr %system %guest %wait %CPU CPU Command 11:49:03 AM 0 2049 0.00 0.20 0.00 0.00 0.20 2 kworker/2:0 11:49:03 AM 64045 3358 0.60 0.20 0.00 0.00 0.80 3 ceph-mon 11:49:03 AM 0 4564 98.41 0.20 0.00 1.39 98.61 0 stress 11:49:03 AM 0 4565 98.81 0.00 0.00 0.99 98.81 1 stress 11:49:03 AM 0 4566 98.21 0.00 0.00 1.39 98.21 0 stress 11:49:03 AM 0 4567 99.20 0.00 0.00 0.60 99.20 2 stress 11:49:03 AM 0 5131 0.20 0.20 0.00 0.40 0.40 0 watch 11:49:03 AM 0 7419 0.20 0.40 0.00 0.00 0.60 3 pidstat 11:49:03 AM 0 26649 0.00 0.20 0.00 0.00 0.20 0 kworker/0:1 11:49:03 AM 0 26658 0.20 0.20 0.00 0.20 0.40 1 sshd 11:49:03 AM 64045 30555 0.60 0.00 0.00 0.00 0.60 1 ceph-osd //
可以从 load average: 4.13 以及 mpstat 的usr 看得出负载场景基本符合CPU 密集型进程 ,pidstat可以看得出是 stress 导致占用率过高。
然后模拟一个I/O 密集型进程
//一终端执行 //root@xxxx:~# stress -i 1 --timeout 600 // 因为 stress 使用的sync系统调用,刷新缓冲区到磁盘。有可能因缓冲区数据量小无法看到io_wait明显变化 root@xxxx:~# stress-ng -i 1 --hdd 1 --timeout 555 stress-ng: info: [9211] dispatching hogs: 1 io, 1 hdd //另一终端 root@xxxx:~# watch -d uptime 16:46:09 up 13 days, 5:38, 3 users, load average: 2.91, 2.56, 1.10 // 另一终端2 //-P ALL 表示监控所有CPU,后面数字5表示间隔5秒后输出一组数据 root@xxxx:~# mpstat -P ALL 5 Linux 4.15.0-66-generic (ECSab169d) 12/22/2020 _x86_64_ (4 CPU) 04:44:02 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle 04:44:07 PM all 1.35 0.00 29.50 26.74 0.00 0.21 0.52 0.00 0.00 41.68 04:44:07 PM 0 2.05 0.00 30.12 26.23 0.00 0.20 0.61 0.00 0.00 40.78 04:44:07 PM 1 0.40 0.00 30.51 51.72 0.00 0.00 0.81 0.00 0.00 16.57 04:44:07 PM 2 0.84 0.00 19.29 19.08 0.00 0.00 0.42 0.00 0.00 60.38 04:44:07 PM 3 1.96 0.00 38.26 8.48 0.00 0.65 0.22 0.00 0.00 50.43 root@xxxx:~# pidstat -u 5 1 04:43:15 PM UID PID %usr %system %guest %wait %CPU CPU Command 04:43:20 PM 0 388 0.00 0.20 0.00 0.00 0.20 0 kworker/0:1H 04:43:20 PM 0 11841 0.00 2.00 0.00 0.00 2.00 1 kworker/1:2 04:43:20 PM 0 12449 0.00 5.40 0.00 0.40 5.40 1 stress-ng-io 04:43:20 PM 0 12450 2.60 60.20 0.00 0.80 62.80 0 stress-ng-hdd 04:43:20 PM 0 22527 0.20 0.20 0.00 0.00 0.40 1 sshd 04:43:20 PM 64045 30555 0.20 0.40 0.00 0.00 0.60 1 ceph-osd
从这里可以看到,1 分钟的平均负载会慢慢增加到 2.91,其中一个 CPU 的系统 CPU 使用率升高到了 30.51,而 iowait 高达 51.72%。这说明,平均负载的升高是由于 iowait 的升高,pidstat 定位到stress进程。
模拟一个大量进程场景
//一终端执行 root@xxxx:~# stress -c 8 --timeout 555 17:00:26 up 13 days, 5:53, 3 users, load average: 7.90, 4.95, 3.04 //另一终端 root@xxxx:~# watch -d uptime 17:00:49 up 13 days, 5:53, 3 users, load average: 7.94, 5.20, 3.17 root@xxxx:~# pidstat -u 5 1 04:43:15 PM UID PID %usr %system %guest %wait %CPU CPU Command 04:43:20 PM 0 388 0.00 0.20 0.00 0.00 0.20 0 kworker/0:1H 04:43:20 PM 0 11841 0.00 2.00 0.00 0.00 2.00 1 kworker/1:2 04:43:20 PM 0 12449 0.00 5.40 0.00 0.40 5.40 1 stress-ng-io 04:43:20 PM 0 12450 2.60 60.20 0.00 0.80 62.80 0 stress-ng-hdd 04:43:20 PM 0 22527 0.20 0.20 0.00 0.00 0.40 1 sshd 04:43:20 PM 64045 30555 0.20 0.40 0.00 0.00 0.60 1 ceph-osd 05:01:33 PM UID PID %usr %system %guest %wait %CPU CPU Command 05:01:38 PM 64045 3358 0.40 0.20 0.00 0.00 0.60 3 ceph-mon 05:01:38 PM 0 5131 0.60 0.20 0.00 0.60 0.80 1 watch 05:01:38 PM 0 9303 0.00 0.20 0.00 0.00 0.20 2 kworker/u8:3 05:01:38 PM 0 13169 0.00 0.20 0.00 0.00 0.20 0 kworker/0:2 05:01:38 PM 0 18138 48.91 0.00 0.00 51.09 48.91 1 stress 05:01:38 PM 0 18139 49.11 0.00 0.00 50.70 49.11 2 stress 05:01:38 PM 0 18140 48.71 0.00 0.00 50.89 48.71 0 stress 05:01:38 PM 0 18141 50.10 0.00 0.00 49.50 50.10 3 stress 05:01:38 PM 0 18142 47.91 0.00 0.00 51.89 47.91 3 stress 05:01:38 PM 0 18143 49.11 0.00 0.00 51.09 49.11 1 stress 05:01:38 PM 0 18144 52.29 0.00 0.00 47.71 52.29 0 stress 05:01:38 PM 0 18145 49.30 0.00 0.00 50.70 49.30 2 stress 05:01:38 PM 0 20608 0.00 0.20 0.00 0.20 0.20 0 pidstat 05:01:38 PM 0 22527 0.00 0.20 0.00 0.00 0.20 2 sshd 05:01:38 PM 64045 30555 0.40 0.00 0.00 0.00 0.40 1 ceph-osd
可以看出,8 个进程在争抢 4 个 CPU,每个进程等待 CPU 的时间(也就是代码块中的 %wait 列)高达 50%。这些超出 CPU 计算能力的进程,最终导致 CPU 过载。
总结
1.CPU密集型进程: 查看 mpstat 是否存在某个CPU %usr 很高但是iowait 很低 , pidstat 定位具体进程(瓶颈不在io)
2.IO密集型进程: mpstat 观察是否有某个cpu的%iowait很高,同时%usr也较高, pidstat 定位具体进程
3.大量进程 : 观察 mpstat 有可能iowait 很低, 但是从 pidstat 看出%wait很高,侧面表现出进程出现竞争cpu
用到命令
lscpu、 grep ‘model name’ /proc/cpuinfo | wc -l : cpu核数
watch -d uptime : 持续观察平均负载
pidstat -u 5 1 : 监测进程对应负载状态,进程性能分析工具
mpstat -P ALL 5 : cpu总体状态 多核cpu性能分析工具,-P ALL监视所有cpu
strees : -c 产生多个worker进程;—cpu-method 使用哪种算法来运行压力测试,包括pi, crc16, fft等等,all选择全部;—sock 调用socket相关函数产生压力; -t, —timeout 等待xx微秒后才开始运行;-i, —io N spawn N workers spinning on sync()