4.1 消息何去何从
mandatory是channel.basicPublish方法中的一个参数,默认为false, 它是当消息传递过程中不可达目的地时消息返回给生产者的功能。rabbitmq提供的备份交换器(alternate exchange)可以将未能被交换器路由的消息(没有绑定队列或者没有匹配的绑定)存储起来,而不用返回给客户端。
当mandatory参数设为true时,交换器 无法根据自身的类型和路由键找到一个符合条件的队列,那么Rabbitmq会调用basicReturn命令将消息返回给生产者,当mandatory参数设置为false时,出现上述情形,则消息直接被弃用。
下面是捕获弃用的方法:
4.1.3 备份交换器
备份交换器(Alternate Exchange)简称AE, 也可称“备胎交换器”。生产者 在发送消息的时候如果不设置mandatory参数,那么消息在未被路由的情况下将丢失;如果设置了mandatory参数,那么需要添加BasicReturn事件的编辑 逻辑,生产者的代码将变得复杂,如果既不想复杂化生产者的编辑 逻辑,又不想消息丢失,那么可以使用备份交换器,这样可以将未被路由的消息存储在rabbitmq中,再需要的时候去处理这些消息。
可以在通过声明交换器(调用channel.ExchangeDeclare方法)的时候添加alternate-exchange参数来实现。添加到arguments中("alternate-exchange","myAe")。
void ExchangeDeclare(string exchange, string type, bool durable, bool autoDelete, IDictionary<string, object> arguments);
下面是一个java示例,如下:
上面代码中声明了两个交换器normalExchange(正常交换器)和myAe(备份交换器),分别绑定了normalQuery(正常队列)和unroutedQueue(未路由队列)。同时将myAe设置为normalExchange的备份交换器,注意myAe的交换器类型为fanout.
如果此时发送一条消息到normalExchange上,当路由键等于 normalKey 的时候,消息能正确路由到noramlQueue这个队列中。如果路由键设为其他值,比如 errorKey即消息不能正确地路由到与normalExchange绑定的任何队列上,此时就会发送给myAe,进而发送到unroutedQueue这个队列。
备份交换器其实和普通交换器没有太大区别,为了方便使用,建议设置为fanout类型,如若读者想设置为direct或者topic的类型也没有什么不妥,需要注意的是,消息被重新发送到备份交换器时的路由键和从生产者发出的路由键是一样的。
考虑这样一种情况,如果备份交换器的类型是direct,并且有一个与其绑定的队列,假设绑定的路由键是key1,当某条携带路由键为key2的消息被转发到这个备份交换器的时候,备份交换器没有匹配到合适的队列,则消息丢失。如果消息携带的路由键为key1,则可以存储到队列中.
对于备份交换器,总结了以下几种特殊情况:
1如果设置的备份交换器不存在,客户端和Rabbitmq服务端都不会有异常出现,此时消息会丢失。
2如果备份交换器没有绑定任何队列,客户端和Rabbitmq服务端都不会有异常出现,此时消息会丢失。
3如果备份交换器没有任何匹配的队列,客户端和Rabbitmq服务端都不会有异常出现,此时消息会丢失。
4如果备份交换器和mandatory参数一起使用,那么mandatory参数无效,也就无法捕获事件basicReturn