Linux 性能分析调优 (四)——案例篇:系统中出现大量不可中断进程和僵尸进程怎么办
之前讲到 CPU 使用率的类型。除了上一节提到的用户 CPU 之外,它还包括系统 CPU(比如上下文切换)、等待 I/O 的 CPU(比如等待磁盘的响应)以及中断 CPU(包括软中断和硬中断)等。
在上下文切换的文章中,一起分析了系统 CPU 使用率高的问题,剩下的等待 I/O的 CPU 使用率(以下简称为 iowait)升高,也是最常见的一个服务器性能问题。今天我们就来看一个多进程 I/O 的案例,并分析这种情况。
目录:
进程状态
当 iowait 升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态。从ps 或者 top 命令的输出中,你可以发现它们都处于 D 状态,也就是不可中断状态
(Uninterruptible Sleep)。既然说到了进程的状态,进程有哪些状态你还记得吗?我们先来回顾一下。
top 和 ps 是最常用的查看进程状态的工具,我们就从 top 的输出开始。下面是一个 top命令输出的示例,S 列(也就是 Status 列)表示进程的状态。从这个示例里,你可以看到R、D、Z、S、I 等几个状态,它们分别是什么意思呢?
- Tasks: total, running, sleeping, stopped, zombie
- Cpu(s): 1.3%us, 0.4%sy, 0.0%ni, 98.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
- Mem: 2054084k total, 1851980k used, 202104k free, 151392k buffers
- Swap: 0k total, 0k used, 0k free, 892636k cached
- PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
- root - 133m 17m R 0.8 0.9 :49.51 AliYunDun
- root D 0.8 0.1 :00.03 top
- root Z 0.4 0.1 :12.22 aliyun-service
- root 2428m 280m 11m S 0.4 14.0 :55.67 java
- root I 0.0 0.1 :00.88 init
- root S 0.0 0.0 :00.03 kthreadd
- root RT S 0.0 0.0 :00.00 migration/
- root S 0.0 0.0 :04.18 ksoftirqd/
- root RT S 0.0 0.0 :00.00 stopper/
- root RT S 0.0 0.0 :03.88 watchdog/
- root S 0.0 0.0 :21.25 events/
- root S 0.0 0.0 :00.00 events/
我们挨个来看一下:
- R 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。
- D 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
- Z 是 Zombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
- S 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。
- I 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。
当然了,上面的示例并没有包括进程的所有状态。除了以上 5 个状态,进程还包括下面这2 个状态。
第一个是 T 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。
向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你用 fg 命令,恢复到前台运行)。
而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。
另一个是 X,也就是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它。
了解了这些,我们再回到今天的主题。先看不可中断状态,这其实是为了保证进程数据与硬件状态一致,并且正常情况下,不可中断状态在很短时间内就会结束。所以,短时的不可中断状态进程,我们一般可以忽略。
但如果系统或硬件发生了故障,进程可能会在不可中断状态保持很久,甚至导致系统中出现大量不可中断进程。这时,你就得注意下,系统是不是出现了 I/O 等性能问题。
再看僵尸进程,这是多进程应用很容易碰到的问题。正常情况下,当一个进程创建了子进程后,它应该通过系统调用 wait() 或者 waitpid() 等待子进程结束,回收子进程的资源
而子进程在结束时,会向它的父进程发送 SIGCHLD 信号,所以,父进程还可以注册SIGCHLD 信号的处理函数,异步回收资源。
如果父进程没这么做,或是子进程执行太快,父进程还没来得及处理子进程状态,子进程就已经提前退出,那这时的子进程就会变成僵尸进程。换句话说,父亲应该一直对儿子负责,善始善终,如果不作为或者跟不上,都会导致“问题少年”的出现。
通常,僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。
一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态。大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建,所以这种情况一定要避免。
案例分析
接下来,我将用一个多进程应用的案例,带你分析大量不可中断状态和僵尸状态进程的问题。这个应用基于 C 开发,由于它的编译和运行步骤比较麻烦,我把它打包成了一个 Docker 镜像。这样,你只需要运行一个 Docker 容器就可以得到模拟环境。运行案例:
- docker run --privileged --name=app -itd feisky/app:iowait
然后,输入 ps 命令,确认案例应用已正常启动。如果一切正常,你应该可以看到如下所示的输出:
- $ ps aux | grep /app
- root 0.0 0.0 pts/ Ss+ : : /app
- root 0.6 0.4 pts/ D+ : : /app
- root 0.6 0.4 pts/ D+ : : /app
从这个界面,我们可以发现多个 app 进程已经启动,并且它们的状态分别是 Ss+ 和D+。
其中,S 表示可中断睡眠状态,D 表示不可中断睡眠状态,我们在前面刚学过,那后面的 s 和 + 是什么意思呢?不知道也没关系,查一下 man ps 就可以。现在记住,s 表示这个进程是一个会话的领导进程,而 + 表示前台进程组。
这里又出现了两个新概念,进程组和会话。它们用来管理一组相互关联的进程,意思其实很好理解。
进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员;而会话是指共享同一个控制终端的一个或多个进程组。
比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。
明白了这些,我们再用 top 看一下系统的资源使用情况:
- # 按下数字 切换到所有 CPU 的使用情况,观察一会儿按 Ctrl+C 结束
- $ top
- top - :: up days, :, users, load average: 2.00, 1.68, 1.39 Tasks: total, running, sleeping, stopped, zombie
- %Cpu0 : 0.0 us, 0.7 sy, 0.0 ni, 38.9 id, 60.5 wa, 0.0 hi, 0.0 si, 0.0 st%Cpu1 : 0.0 us, 0.7 sy, 0.0 ni, 4.7 id, 94.6 wa, 0.0 hi, 0.0 si, 0.0 st ...
- PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND root S 0.0 0.1 :00.88 init
- root D 0.3 0.0 :00.03 app
- root 20 D 0.3 0.04 :00.00 app
- root S 0.0 0.0 :04.19 systemd
从这里你能看出什么问题吗?细心一点,逐行观察,别放过任何一个地方。忘了哪行参数意思的话,也要及时返回去复习。
好的,如果你已经有了答案,那就继续往下走,看看跟我找的问题是否一样。这里,我发现了四个可疑的地方。
先看第一行的平均负载( Load Average),过去 1 分钟、5 分钟和 15 分钟内的平均负载在依次减小,说明平均负载正在升高;而 1 分钟内的平均负载已经达到系统的 CPU个数,说明系统很可能已经有了性能瓶颈。
再看第二行的 Tasks,有 1 个正在运行的进程,但僵尸进程比较多,而且还在不停增加,说明有子进程在退出时没被清理。
接下来看两个 CPU 的使用率情况,用户 CPU 和系统 CPU 都不高,但 iowait 分别是60.5% 和 94.6%,好像有点儿不正常。
最后再看每个进程的情况, CPU 使用率最高的进程只有 0.3%,看起来并不高;但有两个进程处于 D 状态,它们可能在等待 I/O,但光凭这里并不能确定是它们导致了 iowait升高。
我们把这四个问题再汇总一下,就可以得到很明确的两点:
- 第一点,iowait 太高了,导致系统的平均负载升高,甚至达到了系统 CPU 的个数。
- 第二点,僵尸进程在不断增多,说明有程序没能正确清理子进程的资源。
那么,碰到这两个问题该怎么办呢?
小结
主要通过简单的操作,熟悉了几个必备的进程状态。用我们最熟悉的 ps 或者top ,可以查看进程的状态,这些状态包括运行(R)、空闲(I)、不可中断睡眠(D)、可中断睡眠(S)、僵尸(Z)以及暂停(T)等。
其中,不可中断状态和僵尸状态,是我们今天学习的重点。
- 不可中断状态,表示进程正在跟硬件交互,为了保护进程数据和硬件的一致性,系统不允许其他进程或中断打断这个进程。进程长时间处于不可中断状态,通常表示系统有I/O 性能问题。
- 僵尸进程表示进程已经退出,但它的父进程还没有回收子进程占用的资源。短暂的僵尸状态我们通常不必理会,但进程长时间处于僵尸状态,就应该注意了,可能有应用程序没有正常处理子进程的退出。
Linux 性能分析调优 (四)——案例篇:系统中出现大量不可中断进程和僵尸进程怎么办的更多相关文章
- Linux性能分析调优工具介绍
1.常用性能分析工具 1)CPU性能分析工具 vmstat ps sar time strace pstree top 2)Memory性能分析工具 vmstat strace top ipcs ip ...
- 《linux性能及调优指南》 3.5 网络瓶颈
3.5 Network bottlenecks A performance problem in the network subsystem can be the cause of many prob ...
- 《Linux 性能及调优指南》写在后面的话
感谢飞哥的翻译. 目前飞哥 (http://hi.baidu.com/imlidapeng)的网址已经不能访问了. <Linux 性能及调优指南>这本书的原文地址:http://www.r ...
- mysql性能瓶颈分析、性能指标、指标搜集方法与性能分析调优工具
本文主要讲解mysql的性能瓶颈分析.性能指标.性能指标信息的搜集工具与方法.分析调优工具的使用. 文章尚未完成. 性能瓶颈: 慢.写速度比读速度慢很多 主要的性能指标: 访问频度, 并发连接量, ...
- 《Linux 性能及调优指南》2.3 监控工具
翻译:飞哥 (http://hi.baidu.com/imlidapeng) 版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明. 原文名称:<Linux Performance a ...
- 《Linux 性能及调优指南》1.5 网络子系统
翻译:飞哥 (http://hi.baidu.com/imlidapeng) 版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明. 原文名称:<Linux Performance a ...
- 《Linux 性能及调优指南》1.4 硬盘I/O子系统
翻译:飞哥 (http://hi.baidu.com/imlidapeng) 版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明. 原文名称:<Linux Performance a ...
- 《Linux 性能及调优指南》3.1 确认瓶颈
翻译:飞哥 ( http://hi.baidu.com/imlidapeng ) 版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明. 原文名称:<Linux Performance ...
- linux性能查看调优
一 linux服务器性能查看1.1 cpu性能查看1.查看物理cpu个数:cat /proc/cpuinfo |grep "physical id"|sort|uniq|wc -l ...
随机推荐
- 利用SMB jcifs实现对windows中的共享文件夹的操作
需求是在本地上传文件到服务器上,服务器是windows的,使用共享文件夹提供权限给你的. 利用第三方: CIFS (Common Internet File System) SMB(Server Me ...
- AssetBundle打包详解
Unity5.x AssetBundle打包详解 在网上查看了很多资料,想详细搞清楚AssetBundle的原理.以实现符合项目需求的打包工具和加载逻辑 1. AssetBundle是什么? Asse ...
- 2019-03-22-day017-re模块
讲在课前 严格的执行每天的内容 学习的方法 记笔记 课上记框架 画思维导图 常用模块 30分钟 复习 翻笔记 2h 把课上的例子跟着都敲一遍 遇到不会的 自己研究5分钟 还不会 问问同学 再不会 问问 ...
- Hibernate乐观锁无法Catch到org.hibernate.StaleObjectStateException
Hibernate乐观锁无法Catch到org.hibernate.StaleObjectStateException时,请Catch HibernateOptimisticLockingFailur ...
- vue--http请求的封装--session
export function Fecth (url, data, file, _method) { if (file) { // 需要上传文件 return new Promise((resolve ...
- Linux 下各个目录的作用及内容
在 Linux 下,我们看到的是文件夹(目录): 在早期的 UNIX 系统中,各个厂家各自定义了自己的 UNIX 系统文件目录,比较混乱.Linux 面世不久后,对文件目录进行了标准化,于1994年对 ...
- perror strerror使用方法
1. 简介 很多系统函数在错误返回时将错误原因记录在libc定义的全局变量errno中,每种错误原因对应一个错误码. errno在头文件errno.h中声明,是一个整型变量,所有错误码都是正整数.然后 ...
- 对jQuery ajax的认识
1.ajax() 方法通过 HTTP 请求加载远程数据. 2.该方法是 jQuery 底层 AJAX 实现.简单易用的高层实现见 $.get, $.post 等.$.ajax() 返回其创建的 XML ...
- JVM 自带性能监测调优工具 (jstack、jstat)及 JVM GC 调优
1. jstack:占用最多资源(CPU 内存)的Java代码 https://www.cnblogs.com/chengJAVA/p/5821218.html https://blog.csdn.n ...
- rebuild online 创建时,会话被Kill修复索引测试
rebuild online 创建时,会话被Kill修复索引 1.0实验目的:日常运维经常create index online,但是期间被kill会导致索引再次创建失败,测试解决该问题 2.0测试流 ...