记一次队列阻塞的排查历程
开头
开头讲下为什么要记录这次排查历程呢?因为这个问题折腾了我很久,折腾了好几天也尝试过问一些技术的朋友、google查找相对应的资料、包括Stack Overflow上发贴求助、像阿里云发工单,最后运气比较好还是跟另一个同事最后找到了答案。过程比较久,对自己的影响也比较深刻想记录一下。
发生的现象
这个问题是我在帮公司的主要业务从物理机迁移到阿里云上之后发生,遇到的现象是消息队列在每次重启的时候都能正常消费,但是没过多久就队列自己堵住了,并不是业务的代码异常导致。每当堵住后,重启supervisor之后消费又能继续进行,再之后就是这样的一个循环。
排查的过程
我们一开始是把可能出现的问题是放在supervisor上(毕竟看现象是消费者的问题),然后我们怀疑是否是supervisor的配置没有配对,然后找了一篇关于supervisor的文章看了下配置发现supervisor配置就那么多,仔细检查后发现并不是supervisor配置的问题。之后。我们发现同样是rabbitmq:3-management
的镜像,物理机环境的rabbitmq版本跟阿里云rabbitmq版本并不一致(当时就感觉看到了一丝曙光。。。因为阿里云的该镜像是通过docker pull
拉下来的),发现这个问题之后,我就去物理机上通过docker命令docker save -o image.tar rabbitmq:3-management
以及docker load -i image.tar
将rabbitmq的版本跟物理机上保持的一致,但遗憾的是还是没有解决问题,队列堵住还是如期而至。因为我们物理机的rabbtitmq和supervisor是没问题的,期间为了暂时解决这个问题我们将生产者挂在阿里云服务器上,消费者放在物理机的服务器上,但是一开始想的挺美好以为目前至少不会有堵住了,然后没多久就发现我们业务中包含了一些操作本地图片等业务需求,然而我们的图片都在阿里云服务器上这就导致业务出了问题,无奈之下我们还是迁移回了阿里云。当然我们也写了一个定时任务每隔几分钟就重启一次supervisor(虽然有点挫,但是挺无奈)。因为杭州服务器的消费者是没有问题的,我们还是把排查的重心放在了消费者上(期间也有怀疑是否是阿里云的问题,也给阿里云发过工单不过他们都是不是用这个技术栈的,最后也没有问到啥)。我们认为是生产者和消费者在某个时间上断开了通信,因此我到消费的docker容器中安装了tcpdump(CentOs下载的命令:yum install tcpdump),通过命令tcpdump port xxxx
抓生产者和消费者之间的tcp通信,一段时间后队列再次阻塞,tcpdump的结果也跟我们猜想的一致(可以通过tcpdump tcp port xxx -w ./tcp.cap
将记录记录到文件中用专业的工具进行分析),在阻塞后就抓不到任何信息并且执行netstat -nlp | grep xxxx
发现之前消费者的端口未被占用说明连接已经断开了(注:文中的xxxx指的都是消费者监听的端口号)。到了这里终于有了眉目,我们最终怀疑是服务器将进程给kill了,我们的猜测也是通过执行命令dmesg | grep kill
查看到了相应的日志。
造成的原因
造成的原因是linux内核的OOM机制,在内存不足的情况下,会将用户态的进程转到内核态执行,最后按照一定的规则将一个进程kill掉。因为我们物理机是16内存但是迁移到阿里云的服务器配置是8g内存,的确可能存在这个问题,主要还是我疏忽了这一点。。。
解决办法
解决办法目前当然是升级服务器啦,至少保持原先物理机的配置。