平均负载:单位时间内系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。(正在使用和正在等待CPU的进程,ps -aux命令看到的处于R状态(Running或者Runnable)的进程)
可运行状态进程:指正在使用CPU或者正在等待CPU的进程。ps命令中处于R状态的进程。
不可终端状态的进程:指正处于内核态关键流程中的进程,并且这些流程是不可打断的。不可中断状态是系统对进程和硬件设备的一种保护机制。比如,当一个进程像磁盘写数据时,为了保证数据的一致性,在得到磁盘的回复前,它是不能被其他进程或者中断打断的,这个时候进程就处于不可中断的状态。如果此时的进程被打断,就容易出现磁盘数据与进程数据不一致的问题。ps命令中处于D状态的进程。
进程各种状态?
R 运行
S 可中断睡眠 Sleep
D 不可中断睡眠
T 停止的进程
Z 僵尸进程
X 死掉的进程
uptime--查看过去的1分钟、5分钟和15分钟内进程队列中的平均进程数量。
比如当前负载为2时,就意味着什么?
1.在只有2个CPU的系统上,意味着所有的CPU刚好被完成占用
2.在有4个CPU的系统上,意味着CPU有50%的空闲
3.在只有一个CPU的系统中,意味着有一半的进程竞争不到CPU
平均负载多少时合理?
(1)平局负载最理想的状态是等于CPU个数
查看CPU个数,通过CPU命令或者从文件/proc/cpuinfo中读取,或者使用lscpu命令或者使用top命令:
查看物理cpu个数:cat /proc/cpuinfo |grep "physical id"|sort|uniq|wc -l
查看每个物理cpu中的core个数:cat /proc/cpuinfo |grep "cpu cores"|wc -l
逻辑cpu的个数:cat /proc/cpuinfo |grep "processor"|wc -l
物理cpu个数*核数=逻辑cpu个数(不支持超线程技术的情况下)
逻辑核数>物理CPU个数*核数,即开启了超线程
查看CPU核心数grep 'model name' /proc/cpuinfo | wc -l
平均负载和CPU使用率之间的关系?
平均负载包括了正在等待CPU、正在等待CPU和等待I/O的进程
CPU使用率是单位时间内CPU繁忙情况的统计,跟平均负载并不完全对应
1.CPU密集型进程,使用大量CPU会导致平均负载升高,此时两者是一致的
2.I/O密集型进程,等待I/O也会导致平均负载升高。但CPU使用率并不一定高
3.大量等待CPU的进程调度也会导致平均负载升高,此时的CPU使用率也会比较高
查看平均负载
watch uptime
top
w
sar -q 1
dstat -l(-l、-p、-lp)
平均负载分析
使用iostat、mpstat、pidstat、vmstat等工具,找出平均负载高的根源。
vmstat工具:
procs
r:运行和等待cpu时间片的进程数,这个值如果长期大于系统CPU的个数,说明CPU不足,需要增加CPU
b:在等待资源的进程数,比如正在等待I/O、或者内存交换等
memeory
swpd:虚拟内存使用情况,单位为KB。
free:空闲的内存,单位为KB。
buff:被用来作为缓存的内存数,单位为KB。
swap
si:从磁盘交换到内存的交换页数量,单位为KB。
so:从内存交换到磁盘的交换页数量,单位为KB。
如果这个数据不为0,说明系统已经在使用交换区(swap),机器物理内存已经不足。
io
bi:发送到块设备的块数,单位为KB。
bo:从块设备接受的块数,单位为KB。
system
in:每秒的中断数,包括时钟中断。
cs:每秒的环境(上下文)切换次数。
cpu
按cpu的总使用百分比来显示。
us:用户方式下所花费 CPU 时间的百分比。us的值比较高时,说明用户进程消耗的cpu时间多,但是如果长期大于50%,需要考虑优化用户的程序。
sy:显示了内核进程所花费的cpu时间的百分比。这里us + sy的参考值为80%,如果us+sy 大于 80%说明可能存在CPU不足。
wa 列显示了IO等待所占用的CPU时间的百分比。这里wa的参考值为30%,如果wa超过30%,说明IO等待严重,这可能是磁盘大量随机访问造成的,也可能磁盘或者磁盘访问控制器的带宽瓶颈造成的(主要是块操作)。
id:闲置时间。
mpstat -P ALL 1
该命令可以显示每个CPU的占用情况,如果有一个CPU占用率特别高,那么有可能是一个单线程应用程序引起的。
all : 指所有CPU
%usr : 显示在用户级别(例如应用程序)执行时CPU利用率的百分比
%nice :显示在拥有nice优先级的用户级别执行时CPU利用率的百分比
%sys : 现实在系统级别(例如内核)执行时CPU利用率的百分比
%iowait : 显示在系统有未完成的磁盘I/O请求期间CPU空闲时间的百分比
%irq : 显示CPU服务硬件中断所花费时间的百分比
%soft : 显示CPU服务软件中断所花费时间的百分比
%steal : 显示虚拟机管理器在服务另一个虚拟处理器时虚拟CPU处在非自愿等待下花费时间的百分比
%guest : 显示运行虚拟处理器时CPU花费时间的百分比
%idle : 显示CPU空闲和系统没有未完成的磁盘I/O请求情况下的时间百分比系统有两个CPU。如果使用参数 -P 然后紧跟CPU编号得到指定CPU的利用率
用户态CPU使用率高
反映了应用程序的繁忙程度,通常与我们自己写的代码息息相关。
(一)通过top命令查找cpu消耗最多的进程号
(二)通过top -Hp 进程号 找到CPU消耗最多的线程号
(三)通过printf “%x
” 线程号 输出该线程号对应的16进制数字
(四)PID进程在内核调用情况。如果是java应用可以通过jstack 进程号|grep 16进制线程号 -A 10 找到CPU消耗最多的线程方法堆栈。非java程序使用perf top -p 进程号
一、top
用top命令查看各个进程CPU的使用情况,找出占用CPU高的进程的进程id
二、top -Hp 进程ID
通过此命令查看该进程下各个线程的CPU的使用情况,找出占用CPU资源较多的线程ID
三、printf “%x
” 线程号
将找出的占用CPU资源多的线程的ID转换成16进制:printf “%x” 线程号
四、jstack 进程ID(方法一)
命令查看当前java进程的堆栈信息
已经获取的16进制的线程ID对应的是thread dump中的nid参数,找到对应的nid即可;隔段时间再执行一次jstack命令获取thread dump,区分两份dump是否有区别。
五、 jstack 进程ID|grep 转换成16进制的线程ID -A 30(方法二)
其中30为显示的行数
在dump中,线程一般存在如下几种状态
Deadlock,死锁(重点关注)----指多个线程调用间,进入相互资源占用,导致一直等待无法释放的情况。
RUNNABLE,线程处于执行中,指该线程正在执行状态中,该线程占用了资源,正在处理某个请求,有可能正在传递SQL到数据库执行,有可能在对某个文件操作,有可能进行数据类型转换等
Waiting on condition,等待资源或等待某个条件的发生(重点关注)
如堆栈信息明确是应用代码,则证明该线程正在等待资源。
Waiting on monitor entry,等待获取监视器(重点关注)
TIMED_WAITING或者Object.wait(),对象等待中,分为两类:sleeping(线程处于休眠中)和parking(线程处于挂起中)
Suspended,暂停
BLOCKED,线程被阻塞,并等待监视器锁(重点关注)
Parked,停止
根据上述平均负载的定义,能够导致平均负载升高的场景有:
1、处于Running状态的进程大量消耗cpu(CPU密集型进程)
2、大量处于Runnable的进程,cpu会频繁进行上下文切换(寄存器、程序计数器)
操作系统管理的任务包括进程(线程),还有硬件通过触发信号,会导致中断处理程序的调用
上下文切换包括:进程上下文切换(虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态)、线程上下文切换、以及中断上下文切换
特权模式切换:用户态到内核态的上下文切换
怎么确认上下文切换频繁?
每秒钟的上下文切换次数:cat /proc/stat | grep ctxt && sleep 30 && cat /proc/stat | grep ctxt
通过vmstat查看是一个更便捷的方法
上下文切换频繁时怎么排查?
仅靠总的上下文切换次数无法定位到哪个进程或者哪个驱动出的问题,这时就需要pidstat(在sysstat包里)可以查看具体到每个进程每秒的上下文切换次数,下图是执行 $pidstat -w 1的结果
CPU密集型的进程和IO密集型的进程。CPU密集型的进程时间片总是不够用,CPU使用率必然升高,不需要查看上下文切换;而IO密集型的进程,会被频繁调度,但是每次只处理一小会,从CPU使用率是看不出异常的,这时就需要查看上下文切换。一般来讲IO密集型的进程(内核线程或用户进程)主要是处理读写磁盘,或者网络进来的数据;但是也可能有的进程没有任何IO交互但是表现得像IO密集型进程