Linux 性能优化实战
倪朋飞
资深 Linux 专家,Kubernetes 项目维护者
87256 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 65 讲
结束语 (1讲)
Linux 性能优化实战
15
15
1.0x
00:00/00:00
登录|注册

07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上)

高 iowait
僵尸进程不断增多
平均负载升高
思考如何解决这些问题
可疑问题
可能导致 PID 进程号用尽,新进程无法创建
父进程未回收子进程资源
长时间不可中断状态可能导致 I/O 性能问题
短时不可中断状态进程可忽略
保证进程数据与硬件状态一致
X (Dead)
T (Stopped or Traced)
I (Idle)
S (Interruptible Sleep)
Z (Zombie)
D (Disk Sleep)
R (Running)
中断 CPU
等待 I/O 的 CPU
系统 CPU
用户 CPU
案例分析
僵尸进程
不可中断状态
进程状态
CPU 使用率的类型
检查短时应用在捣鬼
CPU 使用率高的分析和应对方法
总结
系统中出现大量不可中断进程和僵尸进程怎么办?

该思维导图由 AI 生成,仅供参考

你好,我是倪朋飞。
上一节,我用一个 Nginx+PHP 的案例,给你讲了服务器 CPU 使用率高的分析和应对方法。这里你一定要记得,当碰到无法解释的 CPU 使用率问题时,先要检查一下是不是短时应用在捣鬼。
短时应用的运行时间比较短,很难在 top 或者 ps 这类展示系统概要和进程快照的工具中发现,你需要使用记录事件的工具来配合诊断,比如 execsnoop 或者 perf top。
这些思路你不用刻意去背,多练习几次,多在操作中思考,你便能灵活运用。
另外,我们还讲到 CPU 使用率的类型。除了上一节提到的用户 CPU 之外,它还包括系统 CPU(比如上下文切换)、等待 I/O 的 CPU(比如等待磁盘的响应)以及中断 CPU(包括软中断和硬中断)等。
我们已经在上下文切换的文章中,一起分析了系统 CPU 使用率高的问题,剩下的等待 I/O 的 CPU 使用率(以下简称为 iowait)升高,也是最常见的一个服务器性能问题。今天我们就来看一个多进程 I/O 的案例,并分析这种情况。

进程状态

当 iowait 升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态。从 ps 或者 top 命令的输出中,你可以发现它们都处于 D 状态,也就是不可中断状态(Uninterruptible Sleep)。既然说到了进程的状态,进程有哪些状态你还记得吗?我们先来回顾一下。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了系统中出现大量不可中断进程和僵尸进程的问题及解决方法。作者首先回顾了进程的状态,包括Running、Disk Sleep、Zombie、Interruptible Sleep、Idle等状态,并解释了它们的含义。随后,作者详细分析了不可中断状态和僵尸状态进程的问题,以及可能导致这些问题的原因。在文章的后半部分,作者提供了一个多进程应用的案例,并带领读者分析了大量不可中断状态和僵尸状态进程的问题。最后,作者提醒读者在操作时避免提前看源码,以便更好地根据现象分析问题。 通过案例分析的方式,本文深入浅出地介绍了系统中出现大量不可中断进程和僵尸进程的问题,对于需要解决类似问题的读者具有一定的参考价值。文章通过实际操作和分析,使读者能够熟悉进程状态,并了解不可中断状态和僵尸状态的重要性。同时,文章引导读者思考如何分析和解决这些问题,为读者提供了实战经验和交流学习的机会。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Linux 性能优化实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(132)

  • 最新
  • 精选
  • 书林
    每个人的机器配置不一样,所以会出现有的机器iowait不明显,有的机器被打爆。解决办法是用docker cgroup选项对 block io做限制。假设硬盘设备为 /dev/nvme0n1,测试如下: 1. 限制块设备的读写 iops 为 3: `docker run --privileged --name=app9 --device /dev/nvme0n1:/dev/nvme0n1 --device-write-iops /dev/nvme0n1:3 --device-read-iops /dev/nvme0n1:3 -itd feisky/app:iowait-new2` 2. 可以查看host机器 cgroup 已为对应 docker container 添加了相关限制: ``` cat /sys/fs/cgroup/blkio/docker/"docker-container-id"/blkio.throttle.write_iops_device 259:0 3 cat /sys/fs/cgroup/blkio/docker/"docker-container-id"/blkio.throttle.read_iops_device 259:0 3 ``` 3. ``` docker exec -it "docker-container-id" /bin/bash root@4cc5e6c74cc0:/# dd iflag=direct if=/dev/nvme0n1 of=/dev/null bs=1k count=1000 1000+0 records in 1000+0 records out 1024000 bytes (1.0 MB, 1000 KiB) copied, 340.004 s, 3.0 kB/s ``` `dd` 每次从 /dev/nvme0n1 设备读取数据写到 /dev/null 设备,每次读取 1kB,一共1000次,必须为 direct 选项。可以观测到拷贝速度为 3 kB/s,即 1kB * 3,说明cgroup 限制 `blkio.throttle.read_iops_device` 生效。 4. 观察host机器 iowait 已经上去。 ``` top - 12:10:22 up 1:25, 1 user, load average: 0.88, 0.81, 0.83 任务: 780 total, 1 running, 227 sleeping, 0 stopped, 552 zombie %Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 s %Cpu1 : 2.7 us, 0.0 sy, 0.0 ni, 97.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 s %Cpu2 : 0.0 us, 0.0 sy, 0.0 ni, 0.0 id,100.0 wa, 0.0 hi, 0.0 si, 0.0 s %Cpu3 : 5.3 us, 7.9 sy, 0.0 ni, 84.2 id, 0.0 wa, 0.0 hi, 2.6 si, 0.0 s MiB Mem : 7863.3 total, 230.4 free, 3847.2 used, 3785.8 buff/cache MiB Swap: 8192.0 total, 8191.5 free, 0.5 used. 3191.1 avail Mem ``` zombie数那么高是因为这个 docker container 已经运行20多分钟了。 供大家参考:)

    作者回复: 谢谢分享,见到Docker高手了😊。 这样的确可以达到IO限制的目的,不过使用系统级工具分析的时候,会有很大不同,比如iostat看看磁盘使用率可能还是很空闲;或者看看内核调用栈也有些不同。 不过这倒是不错的性能隔离方案👍

    2018-12-09
    3
    77
  • 白华
    老师以后的案例能不能使用centos7系统进行操作?做的很多实验和你的都会有部分偏差,这次偏差更大,相信学习你课程的大部分都是用虚拟机跑的项目,用centos系统使用率会很高,而且实际生产中用centos系统肯定大于Ubuntu,造成的实验偏差会不会也是系统的原因。我也遇到了没有出现D状态的进程,出现了大量Z进程。平均负载并没有提升,反而是下降了。iowait并没有变化。所以恳请您使用centos系统来教学吧

    作者回复: iowait不高是因为案例IO操作不够大导致的。我重新推了一个docker镜像,麻烦再试下看看

    2018-12-05
    4
    73
  • 丁兆鹏
    centos7 中模拟一下一起docker中无法启动app docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 54a43bfd9ddb feisky/app:iowait "/app" 7 seconds ago Exited (1) 6 seconds ago app docker logs app也为空。 既然是c程序,使用gdb调试,发现在select_disk() const char *sd_prefix = "sd"; const char *xvd_prefix = "xvd"; ... if (strncmp(sd_prefix, entry->d_name, 2) == 0 || strncmp(xvd_prefix, entry->d_name, 3) == 0) 看看机器上磁盘格式如下: df -h Filesystem Size Used Avail Use% Mounted on /dev/vda1 99G 16G 79G 17% / /dev/vdb1 99G 5.5G 88G 6% /data1 找到原因了,磁盘前缀不同,无法找到的盘,修改app.c代码 const char *sd_prefix = "vd"; const char *xvd_prefix = "vdb"; 然后就可以正常启动了。 docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ceb6eec8129a feisky/app:iowait "/app" 2 seconds ago Up 1 second app

    作者回复: 👍 高手,这是案例考虑不周了,已经在github上增加了参数

    2018-12-17
    8
    34
  • 黄涛
    我是centOS,也是无法启动,参考评论中的方式,修改启动参数为: docker run --privileged --name=app -itd feisky/app:iowait /app -d /dev/vdb1 就可以了

    作者回复: 谢谢分享😊

    2019-06-05
    3
    12
  • 林贻民
    老师您好,我有个疑惑:不可中断状态睡眠不能被其他进程或者中断打断,那照道理说如果不可中断进程很多(超过CPU)逻辑核数时,系统应该处于卡死状态,可是实际上并不是这样的,其他进程照样在执行,说明是存在进程调度,也就是存在重调度中断,键盘输入也有响应,说明也存在硬件中断,这个似乎和不可中断进程状态进程的不可中断产生了冲突?是我有什么地方理解错了吗?

    作者回复: 中断跟不可中断睡眠状态不是一回事,中断是会打断进程运行,而不可中断睡眠是指不可以被信号中断,而不是占着CPU不放了

    2019-03-25
    5
    12
  • 深蓝
    同问,关于Uninterruptible sleep(D)状态 的进程如何有效的处理,以前运维的时候遇到过,貌似只能重启机器,不知道还有什么更好的办法

    作者回复: 一个基本的思路是要找出进程处于 D 状态的原因,是在等待什么样的I/O资源。比如分析系统调用、进程堆栈等等。 找出根源之后,再去分析这些根源里面到底发生了什么,才导致的没有响应。 当然,也有其他比较hack的方法,但生产环境中不推荐,以免给系统带来未知的损坏。

    2018-12-07
    5
  • Brown羊羊
    没有模拟出来系统I/O瓶颈,可以帮忙看下吗: 容器运行起来后只发现一个app进程 [root@liyang2 ~]# ps aux|grep /app root 23619 0.0 0.0 4368 380 pts/0 Ss+ 17:12 0:00 /app root 23777 0.0 0.0 112648 952 pts/0 S+ 17:12 0:00 grep --color=auto /app CPU情况 wa也没有很高 %Cpu(s): 1.0 us, 1.5 sy, 0.0 ni, 94.0 id, 3.3 wa, 0.0 hi, 0.2 si, 0.0 st 系统:redhat7 3.10.0-327.el7.x86_64 x86_64 GNU/Linux

    作者回复: 我的机器配置太弱了,IO已经跑满还是好多人都没有观察到iowait的现象。重新推了一个镜像,加大了IO操作,再试试看现在怎么样

    2018-12-05
    3
    5
  • 姜小鱼
    这个案例的iowait比较高,但是并不影响cpu使用率。因为准确来说,iowait也是属于cpu idle状态的一部分,他和僵尸进程影响的只是平均负载和系统资源

    作者回复: 确切的说是CPU繁忙程度,因为iowait也是CPU使用率的一种类型

    2018-12-05
    2
    4
  • Xg huang
    请教一下老师,一般在写代码访问io的时候,是不可中断还是可中断?

    作者回复: 代码里访问的时候可能会使用缓存,也可能访问到磁盘,访问磁盘的时候是不可中断的

    2019-01-08
    3
  • 近日刚碰到一套生产系统出问题,我们逻辑cpu是120的实体机,跑oracle数据库,业务刚接进来就卡死了,一分钟平均负载200多,运行队列也两百多,cpu的usr部分四五十,sys部分四十左右,iowait基本是零,idle个位数,top和pidstat都无法输出,perftop也无法,只能dstat。请老师指导下思路,在查到底什么问题。

    作者回复: 这种情况应该要适当中断一下应用,让这些基本的操作可以正常执行后重新运行。推荐把这些系统和进程的指标监控起来,避免应用已启动又没法操作了。 还有就是预留几个CPU,专门用作运维、监控使用。这需要修改内核选项

    2018-12-20
    2
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部