线上僵尸进程的现象

主要表现如下:
* 一个NVME磁盘出现掉盘:

  • 存储节点主进程调度程序都不允许,只有一个协程周期打印输出;
  • 查看存储节点主进程状态为pfunc 状态

  • 该进程的内核态堆栈:
    所有的函数,主要停留在下面四个函数里:

[<ffffffff81050cc8>] do_exit+0x8d4/0x8fc 
generic_file_aio_write+0x47/0xa9
sleep_on_buffer+0xe/0x12
wait_transaction_locked+0x8e/0xa7

僵尸进程产生的原理

通常,如果父进程没有waitpid到子进程、子进程就退出了,就会出现僵尸进程,导致无法释放子进程占用的程序资源。

有何影响

  • 存储节点上的存储业务不能正常运行
    先出现IO长尾,然后出现副本切主,长时间没处理的话过期副本会被回收。
  • 如何杀死

    kill -s SIGCHLD pid ​Replace the pid with the id of the parent process so that the parent process will remove all the child processes that are dead and completed. Imagine it Like this :

    “You find a dead body in the middle of the road, you call the dead body’s family and they take that body away from the road.”

    线上僵尸进程的分析

    分析过程

    • 通过进程的内核堆栈,确定有线程退出,也有很多线程停在内核中的等待函数里面
  • 确定上面这些函数都是阻塞的
    这里要注意:read/write操作如果基于文件系统或者块设备,在open的时候没有显式指定O_NOBLOCK flag,但O_NOBLOCK对于文件系统中的普通文件或者块设备没有作用,因为这两者操作到了内核中都会被阻塞。

  • 阅读IO路径直接落盘读写的函数

  • 这个是为了熟悉相关IO路径上直接访问磁盘的函数:
    是否阻塞;
    是否异步;

    • mock这些
      mock 上面的函数,加个控制开关;在新的系统重新部署包含这个改动的二进制。日志级别调节到最详尽;打入测试IO压力,用前面讲的开关控制模拟磁盘异常,观察进程是否变成僵尸。

    经验教训

    熟悉业务的流程和功能能够帮助我们更快定位root cause,后续如果再碰到类似问题。可以从下面几点考虑:

    1. 业务进程之间如何组织;
    2. 磁盘故障之后如何影响用户进程;
    3. 预期的行为应该是怎样?
    4. 可能导致僵尸的进程有哪些?

    参考资料

    https://www.jianshu.com/p/8c476a994069
    https://baike.baidu.com/item/waitpid/4071590?fr=aladdin 介绍waitpid