郑重声明:危险动作,切勿在正式运行环境中模仿。你们搞挂了服务器 ,我概不负责。
我写这篇文档的目的不是让大家去弄崩溃别人的rabbitmq服务器,而是想告诉大家要避免这种情况弄崩溃了自己的rabbitmq服务器。或者对其做出防范。(sui bian ni men zen me gao dou xing)
先讲一下rabbitmq的简单使用方法, rabbitmq相当于一个邮局,也就是一个中间服务器。 大家(生产者)把消息发到这个服务器的某个地址上,然后有人(消费者)去这个地址上拿这个放上去的消息。这个中间的消息服务器是另外的进程,可以在不同的机器上, 所以无论是放东西上去还是去上面拿东西,都需要跟服务器建立连接。 然后在事情处理完成之后再断开连接,就像socket一样。
现在让我复现一下当时我搞崩溃rabbitmq服务器的场景。 因为某种需求, 我需要把一台rabbitmq服务器上某个队列里边的消息复制到另外一台rabbitmq服务器上的另外一个队列上去。于是我就写了一个程序, 先监听第一台rabbitmq上的队列信息,在这里为了偷懒动脑筋,我使用了一种很老司机的写法(因为仅仅只是一个临时的转发程序),如果发现有信息,就连接第二台rabbitmq服务器,把消息发上去之后,再断开第二台服务器的连接。
因为有多个队列的消息需要转发,而且这些队列分别属于不同的虚拟空间,所以需要建立不同的连接,于是就使用了多线程,让每个线程做了这个相同的转发动作,大概有三个不同的虚拟空间,所以最多也就同时起了三个线程的样子。
因为并不是只转发到一台rabbitmq服务器上,所以再发完一个服务器并断开连接之后,再连接第三台rabbitmq服务器,把消息再发给第三台服务器,再断开第二台rabbitmq服务器。 总共是一个rabbitmq服务器上的消息要转发给其他三个rabbitmq服务器。所以每条消息都会依次这样子给三台服务器发送。
现在的逻辑看上去很正常, 都是来消息,然后连接第二台服务器,发送完之后断开连接,再断开连接释放资源。很完美的设计思路!
然而现象是 我的程序跑了大概不到五分钟, 第二台服务器就挂了。 再过几分钟,第三台服务器也挂了。以为是rabbitmq服务有问题,重启了一下,坚持不了五分钟又挂掉了, 又以为是服务器的问题,重新安装了一下rabbitmq服务器,也一样坚持不了多久,当时还不知道rabbitmq服务器挂掉的原因是我的程序引起的,一个劲的再查服务器的问题。
后来我向别人了解实际情况的时候,发现有些消息并不是所有的rabbitmq服务器都需要转发, 我就停止了一些消息对几个rabbitmq服务器的转发。 然后就神奇的发现停止转发的这几个服务器没有再崩溃了。 于是就怀疑到我的这个程序上面来了。然而仔细查阅我的代码, 除了有点老司机的逻辑风格之外, 并没有什么会搞死服务器的骚操作。由于当时那边上午9点才发现是我的程序引起的问题,而十二点的时候就需要去坐地铁赶火车。所以并没有很多的时间去仔细排查和检验是哪里引起的问题。当时大概的看日志就是有个队列的消息来的特别的频繁, 有时候一秒钟都有好多条数据过来。于是我的程序就再反复的对一个rabbitmq服务做连接断开连接断开操作。当时第一感觉就是这个高频率的反复动作引起了这个服务器的死亡高潮。
于是我就修改了这个代码的逻辑, 不再去做反复的连接断开操作, 而是当某个发送信息时遇到连接异常的时候再重连再发送。修改成这样后,rabbitmq服务器就没有再崩溃了。
之后有想过这个为什么反复的连接会弄死服务器的问题,比如觉得在断开连接的时候,有资源没有释放或者没有释放的那么及时,例如断开函数先返回成功,再自己慢慢的释放其他资源。所以在反复的这种骚操作下就崩溃了。然而问题已经解决了,老司机也没有时间去安心弄明白这个问题。简单的百度一下也没有什么线索。只是知道了这样会弄死rabbitmq服务器。
希望大家引以为鉴 (huan ying da jia zuo si)