mandatory和immediate是channel.basicPublish方法中的两个参数,他们都有当消息传递过程中不可达目的地时将消息返回给生产者的功能。RabbitMQ提供的备份交换器(Alternate Exchange)可以将未能被交换器路由的消息(没有绑定队列或者没有匹配的绑定)存储起来,而不是返回给客户端。
mandatory参数
mandatory为true时,交换器无法根据自身的类型和路由键找打一个符合条件的队列,那么RabbitMQ会调用Basic.Return命令将消息返回给生产者。mandatory为false时,出现上述情形,消息直接被丢弃。
生产者通过调用channel.addReturnListener来添加ReturnListener监听器来实现
channel.basicPublish(EXCHANGE_NAME,“”,true,MessageProperties.PERSISTENT_TEXT_PLAIN,“mandatory test”.getBytes());
channel.addReturnListener(new ReturnListener(){
public void handleReturn(int replyCode,String replyText,String exchange,String routingKey,AMQP.BasicProperties basicProperties,byte[] body) throws IOException{
String message = new String(body);
System.out.println("Basic.Return返回的结果是:" + message);
}
})
immediate参数
当immediate参数为true时,如果交换器在将消息路由到队列时发现队列上并不存在任何消费者,那么这条消息将不会存入队列。当与路由键匹配的所有队列都没有消费者时,该消息会通过Basic.Return返回至生产者。
RabbitMQ3.0版开始去掉了对immediate参数的支持
备份交换器
Alternate Exchange,简称AE。生产者在发送消息的时候如果不设置mandatory参数,那么消息在未被路由的情况下将会丢失;如果设置了mandatory参数,需要添加ReturnListener的编程逻辑,生产者的代码将变得复杂。如果不想复杂化生产者的编程逻辑,又不想消息丢失,那么可以使用备份交换器,这样可以将未被路由的消息存储在RabbitMQ中,再在需要的时候处理这些消息。
可以通过在声明交换器(调用cannel.exchangeDeclare方法)的时候添加alternate-exchange参数来实现,也可以通过策略(Policy)的方式实现。如果两者同时使用,则前者的优先级更高,会覆盖掉Policy设置。
Map<String,Object> args = new HashMap<String,Object>();
args.put("altername-exchange","myAe");
channel.exchangeDeclare("normalExchange","direct",true,false,args);
channel.exchangeDeclare("myAe","fanout",true,false,false,null);
channel.queueDeclare("normalQueue",true,false,false,null);
channel.queueBind("normalQueue","normalExchange","normalKey");
channel.queueDeclare("unroutedQueue",true,false,false,null);
channel.queueBind("unroutedQueue","myAe","");
上面的代码声明了两个交换器normalExchange和myAe,分别绑定了normalQueue和unroutedQueue这两个队列,同时将myAe设置为normalExchange的备份交换器,注意myAe的交换器类型为fanout。