版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1434363
概述:
这几天在springboot集成Rabbitmq、Redis、Mongodb、Mybatis、ElasticSearch、Dubbo踩了一堆的坑,今天给大家介绍一下Rabbitmq踩坑史。因为用到Rabbitmq功能比较简单,只是发布订阅和点对点的模式,后期肯定会逐步进行架构升级,会用到Rabbitmq中:发布-订阅模式、点对点模式、顺序消息队列、错误重试、接口等幂性设计、延迟队列。
问题场景:
今天先不介绍功能,主要给大家说一说今天遇到的坑,就是集成Rabbitmq的时候发生一件怪事,消息发送完一直消费不了。我们首先遇到问题一定要先分析一下,而不是一股脑子的开始百度来百度去。我们首先来分析一下出现这个问题可能的原因。
问题分析:
1.消息发送失败,压根就没有发送到Rabbitmq服务中去。
2.消息发送成功,但是因为消费端的问题,导致一直没有消费成功。
3.Rabbitmq本身挂了,所以任何的消息都处理不了了。
4.消息的模式不对,发布消息的key和接收消息的key不一样,所以导致接收不到信息。
问题排查:
针对上面的问题,我们一步步来确定排除一下。
对于第一点:首先如果是发送失败的话,在Rabbitmq服务中肯定看不到任何消息,但是查看Rabbitmq服务的时候发现有信息在,所以这一点可以排除。
至于第二点:我们在服务端进行调试的时候,发现启动没有任何问题,消息从一开始就没有进来过,所以可以肯定不是服务端的问题。
第三点就最好确定了:我们直接打开Rabbitmq服务的控制台,发现Rabbitmq服务没有任何问题,所以这一点也可以排除了。
现在就剩下最后一点了:我们认真的检查了一下,发送的模式和接收的模式,发现一模一样,没有任何不一样的地方,所以最后一条线索也没了。
柳暗花明:
上面几点的猜测,发现都是错误的,我们一时陷入了坑的状态下,后来看控制台发现一个很不一样的地方。(因为控制台我们一般只会关注报错信息,正常打印的信息一般不会去看,这也是这是踩坑的原因)发现有这样的一条输出信息:
Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'mq-exchange' in vhost '/': received 'topic' but current is 'direct', class-id=40, method-id=10)
认真一看,我去。。。上面说发送的消息和接收消息的格式是不一样的,也就是第四点的问题,可是第四点代码里面明明检查过了啊。后来打开Rabbitmq控制台认真一看,还真发现是这个原因,控制台上面exchange模式显示的是direct,但是我们发布的却是topic,难怪消费端消费不到。可是这又有一个问题,这个现象是怎么产生的呢???
刨根问底:
经过我们苦苦从分析查找,发现原来是历史遗留问题。因为我们Rabbitmq服务中本身就有这样的exchange和queue信息了,它们的模式是老早之前就规定好了,也就是direct。这个时候我们重新创建一个一摸一样的exchange和queue信息并不会覆盖上面的信息,所以消息发送就会出现 received 'topic' but current is 'direct'这种问题了。
坑的总结:
这次坑踩的有点憋屈了,因为没有好好看控制台正常情况下的输出日志,导致这种细节问题没有看到,又浪费了很长的时间。不过俗话说得好,凡事都有利弊,好的一点是我们以后在遇到这种情况就可以马上的定位到问题,并解决它。总结一句话:要思考!要认真的思考!要认真谨慎的思考!