当前位置:首页 > python > 正文内容

python 连接rabbitmq出现的诡异进程盗取消息

root5年前 (2020-10-23)python1041

本文在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消费者会立即消失。子进程缓慢关闭。


当然,还是在接下来的开发中,加上对子进程的回收。
哎掉头发的一天,还要感谢公司大佬同事的鼎力支持!方才包住自己的狗头发

    




    

扫描二维码推送至手机访问。

版权声明:本文由一叶知秋发布,如需转载请注明出处。

本文链接:https://zhiqiu.top/?id=20

分享给朋友:

相关文章

Popen 使用注意(python)

Popen 的构造函数可以尝试指定一下 close_fds = True意思是不继承主线程的上下文件因为Popen在启动一个进程时容易出现僵尸进程,当主进程死亡时可能会继承主进程的上下文资源...

python 在centos 执行pip安装包时最好提前执行的语句

yum install python-develpip install --upgrade setuptoolspip install --upgrade pi...

python os 模块文件常用操作

123456import os #回去当前文件路径os.path.realpath(__file__)#获取文件是否存在os.path.exists(filepath)#获取文件大小os.path.getsize(fil...

cmd启动python交互模式 出现UnicodeDecodeError: 'gbk' codec can't decode byte 0x9a in position 533

这是因为在python交互模式的中输出了中文,且是个输出被记录在.python_history中删除历史记录文件C:\Users\Administrator\.python_history...

python用requests发送模拟请求忽略https的认证,忽略警告

import warnings warnings.filterwarnings('ignore')在文件头添加忽略警告信息的输出r = requests.get('https://kyfw.12306.cn&#...

python跟pip不是同一个版本的坑

python执行默认是Python2.7但是pip默认确实pip3的用pip install 安装包只会安装到python3环境里面指回pip vim /usr/local/bin/pip把 第一行的#!/usr/bin...