线上僵尸进程的现象
主要表现如下:
* 一个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,后续如果再碰到类似问题。可以从下面几点考虑:
- 业务进程之间如何组织;
- 磁盘故障之后如何影响用户进程;
- 预期的行为应该是怎样?
- 可能导致僵尸的进程有哪些?
参考资料
https://www.jianshu.com/p/8c476a994069
https://baike.baidu.com/item/waitpid/4071590?fr=aladdin 介绍waitpid