僵尸进程导致CPU使用率持续增高

@lianst  November 16, 2018

前言

最新将生产环境的服务器版本统一升级了一下,其中有一台(4H/8G)近两天天天CPU使用率报警(阀值>95%,探测周期60s,触发频率6次),而且load acerage也居高不下,检查了各个系统应用软件的资源使用都没有问题,也将一些可能导致CPU使用率高的软件stop掉,报警依旧。

排查解决

  1. top
    使用top命令查看,发现占用CPU最高的也就是php-fpm进程(大约35%左右),其次就是在代码发布的时候会触发npm install和npm build操作,但操作完成之后进程就退出了。
  2. 查看日志采集
    top的时候发现好多日志采集filebeat的进程在跑,看了一下filebeat的日志发现一直在报错,所以查看了一下filebeat的版本(主要查看和elasticsearch、kibana版本是否是一直的),结果发现filebeat的版本和elasticsearch、kibana版本不一致,重新更换版本后问题依旧没有解决,但是发现restart filebeat进程的时候,cpu的使用率恢复到了30%左右,此时怀疑和进程有关系。
  3. 调整php-fpm参数
    因为服务器版本升级之后,配置文件是统一同步的,怀疑php-fpm参数配置不合理导致php-fpm进程过高导致CPU使用率飙升。结果调整参数后发现php-fpm reload之后,问题也没有解决,但同样发现了reload之后cpu的使用率恢复到了30%左右,此时更加坚信了CPU的使用率高和某些进程有关系。
  4. 排除法
    既然restart filebeat和reload php-fpm都会让cpu使用率恢复,那么再这两个进程中肯定就有一个进程有问题。使用排除法,一个个暂停检查,发现貌似和php-fpm有关系。
  5. 再次top
    再次打开top,仔细观察各个指标(期间多谢ucloud技术支持),发现有好多php-fpm的Z进程。当时看到Z进程的时候,感觉不太多,没想太多。就我个人而言,Z进程一般不会导致CPU飙这么高。Z进程一般会占用内存空间,虽然也会占用CPU资源,但那都可以忽略不计的。所以,此刻忽略了Z进程,没有对其进行干预操作(疏忽)。
  6. 求助
    无奈之下,联系ucloud技术支持,经过排查,结果真的是Z进程的原因导致的CPU飙升。将Z进程kill后(kill Z进程需要将master进程干掉就可以了),CPU等各项指标恢复正常,问题解决。

总结

  • 升级环境的时候,应用软件的配置、版本没有确认。虽然不是导致此次问题的主要原因,但也是一个潜在的隐患;
  • 在整个排查过程中,没有仔细的检查每一个监控指标;
  • 排查到Z进程的时候,忽略了linux更底层的一些技术特性(或者说原理);

思考

  1. Z进程怎么会占用那么高的CPU使用率
    一开始想不通,Z进程一般是该进程调用了do_exit函数,如果没有与其他进程有共享资源的话,就会吧资源释放掉,变成Z进程,之后仅仅会占用一些内存。翻查资料得到以下解释:

kswapd0 进程占用 CPU 较高的处理,kswapd0 是 Linux 系统虚拟内存管理中负责换页的进程。Linux 系统通过分页机制管理内存的同时,将磁盘的一部分划出来作为虚拟内存。当系统内存不足时,kswapd0 会频繁的进行换页操作。换页操作非常消耗 CPU 资源,导致该进程持续占用高 CPU 资源。如果使用 top 命令,看到 kswapd0 进程持续占用大量 CPU 资源,可以进一步使用 vmstat,查看系统的虚拟内存的情况,如果 si,so 也比较高,证明系统存在频繁的换页操作,当前的系统物理内存已经不能满足需要,考虑升级系统的内存。

当时查看内存使用和top的时候,没有发现内存使用过大(free、cache、buffer),所以才没有说Z进程影响使用率。关于此处,

2.僵尸进程和孤儿进程
在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。 当一个进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。

  孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

  僵尸进程:zombie进程,一般工作中叫Z进程(大写Z),即一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

详细资料:孤儿进程与僵尸进程[总结]

进一步的分析后续补上..


添加新评论