一、系统平均负载
1.概念
平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程
它和 CPU 使用率并没有直接关系
2.负载高的场景
2.1 cpu密集型
CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时系统负载和cpu使用率高是一致的;
2.2 I/O密集型
I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;
2.3 cpu等待调度
大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。
3.环境介绍
3.1 服务器配置
shell
[root@t3-tkhijbs-tkylgw-app01 ~]# cat /proc/cpuinfo |grep -i processor
processor : 0
processor : 1
processor : 2
processor : 3
3.2 安装压测工具
使用stress命令进行压力测试,sysstat包生成pidstat命令,查看进程信息
yum -y install stress sysstat
3.3 stress命令基本使用
shell
1.-c:
完整参数:--cpu N
作用:产生N个进程,每个进程都循环调用sqrt函数产生CPU压力
2.-i:
完整参数:--io N
作用:产生N个进程,每个进程循环调用sync将内存缓冲区内容写到磁盘上,产生IO压力。通过系统调用sync刷新内存缓冲区数据到磁盘中,以确保同步。如果缓冲区内数据较少,写到磁盘中的数据也较少,不会产生IO压力。在SSD磁盘环境中尤为明显,很可能iowait总是0,却因为大量调用系统调用sync,导致系统CPU使用率sys 升高
3.-d:
完整参数:--hdd N
作用:产生N个不断执行write和unlink函数的进程(创建文件,写入内容,删除文件)
4.-t:
完整参数: --timeout N
作用:在N秒后结束程序
4.cpu密集型压测
对4个核心进行压力测试,超时时间为600秒
shell
stress -c 4 -t 600
查看系统负载,发现系统负载变成了5.86.使用top查看,还在持续增长
shell
[root@t3-tkhijbs-tkylgw-app01 ~]# uptime
17:05:45 up 33 days, 3:22, 2 users, load average: 5.86, 2.37, 0.91
使用top或者pidstat查看cpu使用率。这里看出4个进程,每个进程的CPU使用率都是100%
c
05:30:53 PM UID PID %usr %system %guest %CPU CPU Command
05:30:58 PM 0 1 0.00 0.20 0.00 0.20 3 systemd
05:30:58 PM 4000 5297 0.00 0.20 0.00 0.20 2 zabbix_agentd
05:30:58 PM 4000 5337 0.20 0.00 0.00 0.20 2 filebeat
05:30:58 PM 4300 18001 0.20 0.00 0.00 0.20 0 easy_collector
------------------ 可以看出这4个进程每个进程的使用率都是100%
05:30:58 PM 0 21038 100.00 0.00 0.00 100.00 1 stress
05:30:58 PM 0 21039 99.80 0.00 0.00 99.80 2 stress
05:30:58 PM 0 21040 99.80 0.00 0.00 99.80 3 stress
05:30:58 PM 0 21041 99.80 0.00 0.00 99.80 0 stress
--------------------
05:30:58 PM 0 21084 0.00 0.20 0.00 0.20 0 pidstat
5.I/O密集型压测
运行 stress 命令,但这次模拟 I/O 压力。
5.1.查看磁盘容量
shell
[root@t3-tkhijbs-tkylgw-app01 ~]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/rootvg-root xfs 191G 3.8G 187G 2% /
5.2 开始I/O操作
shell
stress -d 4 -t 600
再次查看磁盘大小,使用容量已经到达了8G
shell
[root@t3-tkhijbs-tkylgw-app01 ~]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/rootvg-root xfs 191G 8.0G 183G 5% /
5.3 查看负载
使用top 查看,负载已经变成了4.69. iowaite 已经变成了55%,
shell
top - 11:06:46 up 38 days, 21:23, 3 users, load average: 4.69, 2.24, 0.96
%Cpu(s): 0.2 us, 41.8 sy, 0.1 ni, 2.5 id, 55.0 wa, 0.0 hi, 0.4 si, 0.0 st
可以看到stess的状态全部处于D状态,但是每个进程的CPU的使用率并不是很高。
shell
113414 root 20 0 8216 1124 32 D 44.0 0.0 1:38.11 stress
113416 root 20 0 8216 1124 32 D 42.0 0.0 1:36.08 stress
113413 root 20 0 8216 1124 32 D 41.0 0.0 1:40.00 stress
113415 root 20 0 8216 1124 32 D 40.3 0.0 1:36.71 stress
5.4 查看磁盘I/O
shell
yum -y install iotop
shell
基本用法:
iotop -o: 仅显示实际执行I/O的进程或线程
iotop -b:非交互模式,批量处理用来记录日志的
iotop -n [次数]: 设定循环几次
iotop -p [进程/线程] :查看指定进程的读写
iotop -P 只显示进程
查看结果如下:
shell
Total DISK READ : 0.00 B/s | Total DISK WRITE : 3.95 G/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 2.41 G/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
113079 be/4 root 0.00 B/s 0.00 B/s 0.00 % 61.41 % [kworker/u256:2]
114406 be/4 root 0.00 B/s 516.66 M/s 0.00 % 36.82 % stress -d 4 -t 600
114409 be/4 root 0.00 B/s 762.88 M/s 0.00 % 34.96 % stress -d 4 -t 600
114408 be/4 root 0.00 B/s 711.30 M/s 0.00 % 32.77 % stress -d 4 -t 600
114407 be/4 root 0.00 B/s 544.27 M/s 0.00 % 32.36 % stress -d 4 -t 600
解释:
Actual DISK WRITE: 是实际磁盘写入的数据
二、线程
这里要先讲一下线程,才能为下边单进程的cpu使用率做铺垫
1.线程概念
线程是进程的子单位,是真正执行任务的单元。而进程是资源分配的单位
2.安装pidstat命令
sehll
yum -y install sysstat
3.启动多线程
3.1 代码内容
使用python生成多个线程,代码如下
c
cat test.py
from concurrent.futures import ThreadPoolExecutor
import time
# 启动线程池,启动10个线程
spool = ThreadPoolExecutor(10)
task_list = [ i for i in range(100)]
def test(list):
print(list)
time.sleep(1000)
def main():
for i in task_list:
spool.submit(test,i)
if __name__ == "__main__":
main()
2.2 启动多线程
shell
python3 test.py
4.查看进程
c
[root@node4 test]# ps aux |grep test
root 22200 0.2 1.3 937428 13372 pts/0 Sl+ 05:00 0:00 python3 test.py
4.1 查看进程中的线程
方法1:top
shell
top -H -p 22200
方法2:pidstat
shell
pidstat -t -p 22200
内容如下:
这里可以看出,python启动的程序一共有10个线程
c
[root@node4 ~]# pidstat -t -p 22200
Linux 3.10.0-693.el7.x86_64 (node4) 04/29/2024 _x86_64_ (4 CPU)
03:30:16 AM UID TGID TID %usr %system %guest %CPU CPU Command
03:30:16 AM 0 21582 - 0.00 0.00 0.00 0.00 2 python3
03:30:16 AM 0 - 21582 0.00 0.00 0.00 0.00 2 |__python3
03:30:16 AM 0 - 21583 0.00 0.00 0.00 0.00 3 |__python3
03:30:16 AM 0 - 21584 0.00 0.00 0.00 0.00 0 |__python3
03:30:16 AM 0 - 21585 0.00 0.00 0.00 0.00 3 |__python3
03:30:16 AM 0 - 21586 0.00 0.00 0.00 0.00 3 |__python3
03:30:16 AM 0 - 21587 0.00 0.00 0.00 0.00 3 |__python3
03:30:16 AM 0 - 21588 0.00 0.00 0.00 0.00 3 |__python3
03:30:16 AM 0 - 21589 0.00 0.00 0.00 0.00 3 |__python3
03:30:16 AM 0 - 21590 0.00 0.00 0.00 0.00 3 |__python3
03:30:16 AM 0 - 21591 0.00 0.00 0.00 0.00 3 |__python3
03:30:16 AM 0 - 21592 0.00 0.00 0.00 0.00 3 |__python3
解释:
shell
TGID : 进程ID
TID: 线程ID
三、单进程的cpu使用率
1.cpu使用率的概念
上述中讲了平均负载的概念,平均负载与CPU使用率并没有直接的关系。这里来看看cpu使用率到底是什么意思。
1.1 时间片
Linux 作为一个多任务操作系统,将每个 "CPU 的时间" 划分为很短的 "时间片",再通过调度器轮流分配给各个任务使用,因此造成多任务同时运行的错觉。
1.2 cpu时间片相关参数
在top命中可以到一下参数
c
%Cpu(s): 1.5 us, 1.5 sy, 0.0 ni, 96.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
解释:
shell
1. user(us),代表用户态 CPU 时间。注意,它不包括下面的 nice 时间,但包括了 guest 时间。
2. nice(ni),代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。这里注意,nice 可取值范围是 -20 到 19,数值越大,优先级反而越低。
3. system(sys),代表内核态 CPU 时间。
4. idle(id),代表空闲时间。注意,它不包括等待 I/O 的时间(iowait)
5. iowait(wa),代表等待 I/O 的 CPU 时间
6. irq(hi),代表处理硬中断的 CPU 时间。
7. softirq(si),代表处理软中断的 CPU 时间。
8. steal(st),代表当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间。
1.3 cpu使用率
CPU 使用率,就是除了空闲时间外的其他时间占总 CPU 时间的百分比。
只是在top中把 CPU 时间变换成了 CPU 使用率。
2.单进程多线程cpu超过100
cpu核心数量为8核心
c
[root@p0-tkhijbs-jenkins-app01 ~]# cat /proc/cpuinfo |grep processor
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5
processor : 6
processor : 7
2.1.代码如下:
这里使用了c语言写了一个简单的多线程的程序。
这里之所以使用的C 是因为C、c++、java语法多线程是真正的使用了多核心技术.而python语言只能使用总核心的一半。不知道是不是我代码的问题
c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* thread_function(void* arg) {
while(1) {
}
return NULL;
}
int main() {
# 这里的8是线程的数量,和cpu的核心的数量一致或者小于即可
pthread_t threads[8];
int i;
# 这里的6就是上边的生成线程的数量
for(i = 0; i < 8; i++){
if(pthread_create(&threads[i], NULL, &thread_function, NULL) != 0) {
fprintf(stderr, "线程创建失败\n");
return 1;
}
}
# 这里的6就是上边的生成线程的数量
for(i = 0; i < 8; i++){
pthread_join(threads[i], NULL);
}
return 0;
}
2.2 编译
如果编译报错:
c
[root@p0-tkhijbs-jenkins-app01 ~]# gcc test.c
/tmp/cctoYACU.o: In function `main':
test.c:(.text+0x3f): undefined reference to `pthread_create'
test.c:(.text+0x92): undefined reference to `pthread_join'
collect2: error: ld returned 1 exit statu
解决办法:
c
[root@p0-tkhijbs-jenkins-app01 ~]# gcc test.c -lpthread
2.3 运行
c
./a.out
2.4 使用top查看负载
基本参数:
shell
-b: 以批处理模式运行top命令,不需要交互式操作。输出结果可以重定向或管道符输出到文件或其他命令中
-i: 忽略闲置进程,只显示活跃的进程。活跃进程是指CPU或其他资源使用率高的进程
-d: 指定top命令更新的时间间隔,单位为秒,默认值是3秒
-H: 查看进程的线程
-p: 指定pid
查看命令:
c
[root@p0-tkhijbs-jenkins-app01 ~]# top -b -i
top - 19:28:56 up 1454 days, 1:35, 2 users, load average: 3.22, 0.77, 0.29
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29161 root 20 0 22872 376 296 S 762.5 0.0 3:16.54 a.out
......
......
......
top - 19:30:16 up 1454 days, 1:36, 2 users, load average: 8.23, 2.97, 1.11
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29161 root 20 0 22872 376 296 S 800.0 0.0 13:53.34 a.out
这里看到 a.out程序的%cpu已经达到%800.这里就出现了单进程的cpu使用率超过了100%的现象
2.5 查看a.out的线程
c
[root@p0-tkhijbs-jenkins-app01 ~]# pidstat -p 29161 -t
Linux 3.10.0-693.el7.x86_64 (p0-tkhijbs-jenkins-app01) 05/07/2024 _x86_64_ (8 CPU)
07:33:54 PM UID TGID TID %usr %system %guest %CPU CPU Command
07:33:54 PM 0 29161 - 0.00 0.00 0.00 0.00 4 a.out
07:33:54 PM 0 - 29161 0.00 0.00 0.00 0.00 4 |__a.out
07:33:54 PM 0 - 29162 0.00 0.00 0.00 0.00 5 |__a.out
07:33:54 PM 0 - 29163 0.00 0.00 0.00 0.00 6 |__a.out
07:33:54 PM 0 - 29164 0.00 0.00 0.00 0.00 0 |__a.out
07:33:54 PM 0 - 29165 0.00 0.00 0.00 0.00 2 |__a.out
07:33:54 PM 0 - 29166 0.00 0.00 0.00 0.00 1 |__a.out
07:33:54 PM 0 - 29167 0.00 0.00 0.00 0.00 3 |__a.out
07:33:54 PM 0 - 29168 0.00 0.00 0.00 0.00 7 |__a.out
07:33:54 PM 0 - 29169 0.00 0.00 0.00 0.00 4 |__a.out