RabbitMQ系列P3—Return机制

149 阅读2分钟

  本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

前言

  我们都知道,在RabbitMQ中,生产端生产消息,然后投递到Broker中,若是交换机通过路由键能找到与之绑定的队列,则会将消息存入队列中,然后由消费者调用消费。那么如果在Broker中,交换机找不到相应的队列,那么此时消息应该何去何从呢?

  在channel.basicPublish方法中有一个参数,mandatory,当这个参数为true时,若是交换机找不到与之对应的队列,则RabbitMQ将会调用Basic.Return命令将消息返回给生产者;当mandatoryfalse时,出现上述场景时,则消息直接被丢弃。因此可通过在生产端调用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监听器将那些无法被绑定的消息发送回生产端