本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
前言
我们都知道,在RabbitMQ中,生产端生产消息,然后投递到Broker中,若是交换机通过路由键能找到与之绑定的队列,则会将消息存入队列中,然后由消费者调用消费。那么如果在Broker中,交换机找不到相应的队列,那么此时消息应该何去何从呢?
在channel.basicPublish方法中有一个参数,mandatory,当这个参数为true时,若是交换机找不到与之对应的队列,则RabbitMQ将会调用Basic.Return命令将消息返回给生产者;当mandatory为false时,出现上述场景时,则消息直接被丢弃。因此可通过在生产端调用channel.addReturnListener添加ReturnListener监听器,将这些不可达消息返回给生产端。下面是示例代码
public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection= ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
String exchangeName="exchange_return";
//正确的routingKey
String routingKey="return.test";
//错误的的routingKey
String errRoutingKey="err.key";
String message="test for return";
//参数mandatory设为true
channel.basicPublish(exchangeName, errRoutingKey, true, null,message.getBytes());
//在publish之后添加监听器
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("replyCode:"+replyCode);
System.out.println("replyText:"+replyText);
System.out.println("exchange:"+exchange);
System.out.println("routingKey:"+routingKey);
System.out.println("message:"+new String(body));
System.out.println("exchange:"+exchange+"与 routingKey:"+routingKey+"没有找到绑定的队列,返回的消息为"+new String(body));
}
});
//不要关闭链接
// channel.close();
// connection.close();
}
}
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
String exchangeName="exchange_return";
String type="topic";
String queueName="queue_return";
String routingKey="return.test";
channel.exchangeDeclare(exchangeName, type, true);
channel.queueDeclare(queueName, true, false, false, null);
channel.queueBind(queueName, exchangeName, routingKey);
channel.basicConsume(queueName, true, new DefaultConsumer(channel));
}
}
先启动Consumer,再启动Producer,生产端控制台输出:
replyCode:312
replyText:NO_ROUTE
exchange:exchange_return
routingKey:err.key
message:test for return
exchange:exchange_return与 routingKey:err.key没有找到绑定的队列,返回的消息为test for return
总结
使用RabbitMQ的时候,可以在生产端配置mandatory参数和ReturnListener监听器将那些无法被绑定的消息发送回生产端