python 连接rabbitmq出现的诡异进程盗取消息
本文在py2下执行,
由来:
因业务需要,python创建子线程后再次创建子进程(用于执行shell命令)。没错就是在子线程里面创建子进程。都知道py2的坑还是蛮多的。
问题出现:在某次运行中出现了一个情况,mq的管理界面有一个消息一直是unack状态。通过查看发送端的信息,在接收端中的数据库中并没有找到该数据。
在mq管理面板发现了两个消费者,消费的ip地址还一样,只是端口不一样。通过这里的两个不同的端口去查看服务器到底是什么程序占用这个端口。
发现一个是正常的主进程,一个是子进程x。
顿时头皮发麻,子进程没有丝毫接收mq消息的代码,而且都是比较简单的shell命令。
但是发现的x子进程的进程号都比主进程号小,极其的不正常。
然后kill掉正常的主进程,mq管理面板的消费者少一个,讲道理现在一个消费者都不应该有。通过剩余的消费者的端口号查看服务器的服务
发现是刚才的x子进程。为什么这个x子进程没有挂?这是个问题。
我再次重启程序,主进程启动,mq的消费者增加一个。服务器的服务还是主进程和之前的x子进程占用端口消费消息。
好在这个有问题的消费者只消费了一个且一直是unack。
再次kill掉主程序,然后剩下x子进程。这很可能是之前某次主进程启动触发的,关闭主进程后并没有随着关闭。
当关闭主进程之后,在关闭这个x子进程,处于unack的消息被释放重新进入ready状态,可以被消费。
主问题:关闭主进程,出现子进程没有关闭,且消费了一个mq消息。,bug不可主动重现,且重现率极低。
问题1:为什么子进程没有关闭?以后还出重现吗?
解决思路就是关闭主线程的时候干掉子线程。
问题2:为什么子线程会接收mq消息,子线程的业务关系跟mq没有任务关联。
存在的关联关系是:rabbitmq的消费出现一个unack的,必然有一个僵尸子进程存在
存在的现象:当两次启停主程序时,会出现两个消费者和第一次主程序的僵尸进程。但是过一会僵尸进程和一个消费者就会消失。
疑惑之处:启动一次主程序会在运行中多次启动子进程,代码中并没有强制随主进程关闭,但是自己执行完会关闭。因为关闭主进程时,子进程的数远小于创建的子进程数。且过数秒钟所有子进程就全部关闭。
经过和同事的分析和查看linux的进程运行信息。
初步猜想:子进程存在某些原因没有关闭(先不管什么原因),子进程会继承主进程的资源,包含消费的端口资源等,这个子进程成为僵尸进程,占用端口,保持连接,但是无法处理消息。
首要处理方案:
关闭主进程时,逐一把所有没有关闭的子进程关闭。避免僵尸进程的出现。
执行方案:
在主进程中开启的子进程设置为独立的,不在继承主进程的资源。
执行效果:关闭主程序是,mq消费者会立即消失。子进程缓慢关闭。
当然,还是在接下来的开发中,加上对子进程的回收。
哎掉头发的一天,还要感谢公司大佬同事的鼎力支持!方才包住自己的狗头发