rabbitmq 之mandatory和immediate 以及 备份交换器
1. 概述
mandatory和immediate是AMQP协议中basic.publish方法中的两个标识位,它们都有当消息传递过程中不可达目的地时将消息返回给生产者的功能。对于刚开始接触RabbitMQ的朋友特别容易被这两个参数搞混,这里博主整理了写资料,简单讲解下这两个标识位。
mandatory
当mandatory标志位设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返回给生产者(Basic.Return + Content-Header + Content-Body);当mandatory设置为false时,出现上述情形broker会直接将消息扔掉。
immediate
当immediate标志位设置为true时,如果exchange在将消息路由到queue(s)时发现对于的queue上么有消费者,那么这条消息不会放入队列中。当与消息routeKey关联的所有queue(一个或者多个)都没有消费者时,该消息会通过basic.return方法返还给生产者。
概括来说,mandatory标志告诉服务器至少将该消息route到一个队列中,否则将消息返还给生产者;immediate标志告诉服务器如果该消息关联的queue上有消费者,则马上将消息投递给它,如果所有queue都没有消费者,直接把消息返还给生产者,不用将消息入队列等待消费者了。
在RabbitMQ3.0以后的版本里,去掉了immediate参数的支持,发送带immediate标记的publish会返回如下错误:
“{amqp_error,not_implemented,“immediate=true”,‘basic.publish’}”
为什么移除immediate标记,参见如下版本变化描述:
immediate标记会影响镜像队列性能,增加代码复杂性,并建议采用“TTL”和“DLX”等方式替代。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
生产者在发送消息时不设置mandatory 参数,那么消息达到路由器后匹配不到相应的队列后消息将会丢失。
设置了mandatory 参数,那么需要添加ReturnListener的编程逻辑。
如果既不想复杂化生产者的编程逻辑,又不想消息丢失,那么可以使用备份交换器。
顾名思义 备份交换器就是当第一个交换器未能有效匹配到队列时,路由到备份交换器,再由备份交换器区匹配队列
备份交换器需要注意的是:
如果交换器的名字之前声明过了在RabbitMQ中已经存在,便不可修改添加参数,修改会报错。
解决方案:换个交换器的名字或者删除之前的交换器
注意点:
如果设置的备份交换器不存在,客户端和RabbitMQ 服务端都不会有异常出现,此时消息会丢失。
如果备份交换器没有绑定任何队列,客户端和RabbitMQ 服务端都不会有异常出现,此时消息会丢失。
如果备份交换器没有任何匹配的队列,客户端和RabbitMQ 服务端都不会有异常出现,此时消息会丢失。
如果备份交换器和mandatory 参数一起使用,那么mandatory 参数无效( 不会返还给生产者 )。即备份交换机优先于mandatory