相信很多同学都遇到过服务器卡的情况,比如SSH登录缓慢,敲命令延迟大,web服务响应超时等等,遇到这种情况一般怎么办呢?当然是top一下了,大多数情况下你会欣喜的发现CPU使用率确实高了,再通过ps命令最终定位到了引起这次延迟的罪魁祸首,恭喜你,你已经掌握了定位负载高的常用手段。
但是,你发现自己并不是每次都那么幸运,偶尔也有失手的时候,top发现cpu使用率很低啊,甚至不到10%,此时的你可能又会陷入绝望了,这是怎么回事呢,明明CPU那么空闲,怎么还会这么卡呢?此时你有free了一下看了看内存剩余也挺多啊,这下就更绝望了。别急,下面我们慢慢揭开这引起系统卡顿的背后黑手。
其实,你遗漏的线索就在top命令的第一行。可能是top输出的信息太多,看起来脑袋都大了。那现在我就告诉你一个查看负载特别简洁的命令uptime,你会发现uptime命令的输出结果就是top的第一行输出。但是看着是不是清爽很多啊。
uptime
20:23pm up 78 days 3:37, 1 user, load average: 0.10, 0.04, 0.05
虽然命令简单,输出信息少,但是你真的理解输出的每列的含义吗?
当我们不知道这个命令的含义怎么办呢?相信大部分同学都会百度一下,这是个好习惯,但是我建议你先不要百度,可以先man一下该命令。
uptime gives a one line display of the following information. The current time, how long the system has been running, how many users are currently logged on, and the system load averages for the past 1, 5, and 15 minutes.
从以上man uptime的描述中我们看到,前三列的意思分别是现在是时间,系统运行时间和正在登陆的用户数。但是后面过去1分钟、5分钟、15分钟的平均负载是什么意思呢?
这就是今天写这篇文章的原因,你在工作中也许经常“平均负载”这个词,但也许并不能确切的知道它真实的含义。其实uptime这个命令是从/proc/loadavg这个文件中读取的。当你再次man proc时会发现对/proc/loadavg这个文件的描述。这里有对平均负载更进一步的解释。
The first three fields in this file are load average figures giving the number of jobs in the run queue (state R) or waiting for disk I/O (state D) averaged over 1, 5, and 15 minutes
后面三列的意思解释起来就是1分钟、5分钟和15分钟内,系统处于运行队列(R状态)和等待磁盘I/O(D状态)的平均进程数,也就是平均活跃进程数。
那R状态和D状态又是什么呢?
运行队列或者可运行状态(R状态)包括了正在CPU运行中的(Running)和准备就绪等待CPU的(Runable)的进程数,所有进程必须切换到该状态的进程才可能在CPU上运行。等待磁盘I/O(disk sleep)又叫不可中断睡眠状态(uninterrupt sleep)是指进程处于睡眠状态,但是此进程又是不可中断的,也就是它是不会响应系统给他的信号的,比如kill命令,你会发现处于此状态的进程即使是kill -9 也不会把它杀死。此状态存在的意义就在于,内核的某些处理流程是不能被打断的,比如进程在读写磁盘时为了保护数据一致性,是不可以被打断的,除非它已经处理完,会自动退出该状态。
当然还有其他状态如S状态,处于这个状态的进程因为等待某某事件的发生(比如等待socket连接、等待信号量),而被挂起,通过ps命令我们会看到,一般情况下,进程列表中的绝大多数进程都处于TASK_INTERRUPTIBLE状态(除非机器的负载很高)。毕竟CPU就这么一两个,进程动辄几十上百个,如果不是绝大多数进程都在睡眠,CPU又怎么响应得过来。
Z状态也就是僵尸进程,Z进程也是不能被杀死的,因为他已经死了,所以才被称为僵死进程,我们知道每个进程(pid)都有一个父进程(ppid),一个子进程退出时,它所占用的资源比如内存和一些系统表等都会被父进程回收,如果此时子进程异常退出时,父进程没有感知到子进程就会变成僵尸进程,他会占用额外的资源,如果这样的进程多了,就会引起系统问题。
而CPU负载最主要的就是跟R和D两个状态有关。可以使用 ps aux命令查看
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 6982 0.0 0.0 815668 4792 pts/2 R+ 21:44 0:00 ps -aux
root 8059 0.0 0.0 0 0 ? S< 2018 1:43 [kworker/0:1H]
root 8109 0.0 0.0 0 0 ? S 2018 3:16 [jbd2/vdb-8]
root 8110 0.0 0.0 0 0 ? S< 2018 0:00 [ext4-rsv-conver]
root 8214 0.0 0.0 0 0 ? S 2018 0:00 [kauditd]
root 8934 0.0 0.2 258060 16416 ? Sl 2018 1:36 /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
root 9078 0.0 0.0 0 0 ? S< 2018 0:54 [kworker/1:1H]
root 9201 0.0 0.0 64116 1200 ? Ss 2018 6:22 /usr/sbin/sshd
root 9419 0.0 0.0 6296 268 ? Ss 2018 0:00 /usr/sbin/mcelog --daemon
ntp 9612 0.0 0.0 727736 5160 ? Ss 2018 0:17 ntpd -u ntp:ntp -p /var/run/ntpd.pid -g
root 9800 0.0 0.0 78720 3268 ? Ss 2018 1:02 /usr/libexec/postfix/master
root 106222 0.1 0.0 137484 3748 ? Ssl Jan03 22:12 ./bin/redis-server *:8000 [cluster]
其中stat列的含义是
R 正在运行,或在队列中的进程
S 处于休眠状态
T 停止或被追踪
Z 僵尸进程
W 进入内存交换(从内核2.6开始无效)
X 死掉的进程
< 高优先级
N 低优先级
L 有些页被锁进内存
s 包含子进程
+ 位于后台的进程组;
l 多线程,克隆线程 multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
啰啰嗦嗦了这么多,cpu平均负载简单说就是单位时间内处于R状态和D状态的平均进程数,所以CPU使用率高,平均负载会升高,但是平均负载升高并不一定是CPU使用率高,也可能是IO达到了瓶颈,此时你可以通过iostat观察系统的io情况。
但是cpu负载多少合适呢?有人说肯定越小越好,回答正确,确实是这样的。但是多少会引起瓶颈呢?我们上篇文章 Linux篇:(1)cpu之基础知识 提到,一个CPU在某一个时刻只能处理一个线程,所以对于单核CPU来说,cpu平均负载等于1说明正好有一个进程在运行,CPU等于0.5说明CPU有50%的时间是空闲的,CPU平均负载等于2说明有一半的进程在排队。但是对于双核CPU来说,平均负载等于1说明有50%的时间是空闲的,平均负载等于2说明刚和进程占满CPU时间。但是为了留有buffer,一般认为平均负载/cpu核数>0.7就要关注系统性能问题了。
问题又来了?是看1分钟负载、5分钟负载还是15分钟负载呢?答案是都要看,这三个指标对比反映了系统的性能变化趋势,比如1分钟负载>5分钟负载>15分钟负载说明系统性能问题正在恶化,1分钟负载<5分钟负载<15分钟负载说明系统性能问题正在好转,如果三个指标差不多,说明系统问题很稳定。
小编前段时间就遇到了一种现象,晚上刚吃过饭收到线上大量报警短信,kubernetes集群的一台主机CPU负载居然高达300左右,此时小编赶紧登陆服务器查询系统发现1分钟、5分钟、15分钟负载稳定在300左右。通过top查看CPU使用率很低,那应该是io问题了,通过iostat也没有发现IO存在瓶颈。真是奇怪,小编就想到了是不是D状态的线程比较多呢,通过ps命令发现处于D状态的线程289个,加上一个R状态的线程正好300左右。我们知道D状态是不可中断状态,怎么解决呢?当然是重启了,哈哈!
下期预告:Linux篇:(3)cpu之CPU使用率到底是怎么计算的