美文网首页rabbitmq
rabbitmq 死信队列

rabbitmq 死信队列

作者: HmilyMing | 来源:发表于2019-02-02 22:50 被阅读26次

死信队列: DLX,dead-letter-exchange

利用 dlx,当消息在一个队列中变成死信 (dead message) 之后,它能被重新 publish 到另一个 exchange,这个 exchange 就是 dlx

消息变成死信的原因有:

1.消息被拒绝 (basic.reject / basic.nack) 并且 reQueue=false

2.消息 TTL 过期

3.队列达到最大长度了

dlx 也是一个正常的 exchange,和一般的 exchange 没什么区别,它能在任何队列上被指定,实际上就是设置一个属性。

当这个队列中有死信时,rabbitMQ 就会自动的将这个消息重新发布到设置的 exchange 上去,进而被路由到另一个队列。

可以监听这个队列中消息做相应的处理,这个特性可以弥补 rabbitMQ3.0 以前支持的 immediate 参数功能。

死信队列的设置:

首先要设置死信队列的 exchange 和 queue,然后进行绑定:

  exchange: dlx.exchange

  queue: dlx.queue

  routingkey:  #

然后进行正常声明交换机、队列、绑定,只不过需要在队列加上一个参数即可: argument.put("x-dead-letter-exchange", "dlx.exchange");

这样消息在过期、reQueue、队列在达到最大长度时,消息就可以直接路由到死信队列

代码地址:    https://github.com/hmilyos/rabbitmqdemo.git  rabbitmq-api 项目下
public class Producer {

    private static final Logger log = LoggerFactory.getLogger(Producer.class);
    
    public static void main(String[] args) throws IOException, TimeoutException {
         ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost(RabbitMQCommon.RABBITMQ_HOST);
            connectionFactory.setPort(RabbitMQCommon.RABBITMQ_PORT);
            connectionFactory.setVirtualHost(RabbitMQCommon.RABBITMQ_DEFAULT_VIRTUAL_HOST);

            Connection connection = connectionFactory.newConnection();
            Channel channel = connection.createChannel();

            //注意,这只是普通的交换机和routingKey
            String exchange = "test_dlx_exchange";
            String routingKey = "dlx.save";

            for (int i = 0; i < 1; i++) {
                String msg = "Hello RabbitMQ DLX Message" + i;
                AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
                        .deliveryMode(2)
                        .contentEncoding("UTF-8")
                        .expiration("10000")
                        .build();
                log.info("生产端发送:{}", msg);
                channel.basicPublish(exchange, routingKey, true, properties, msg.getBytes());
            }
    }
}

/**
 *   死信队列
 *
 */
public class Consumer {

    private static final Logger log = LoggerFactory.getLogger(Consumer.class);
    
    public static void main(String[] args) throws IOException, TimeoutException {
        //1 创建ConnectionFactory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(RabbitMQCommon.RABBITMQ_HOST);
        connectionFactory.setPort(RabbitMQCommon.RABBITMQ_PORT);
        connectionFactory.setVirtualHost(RabbitMQCommon.RABBITMQ_DEFAULT_VIRTUAL_HOST);
        //2 获取Connection
        Connection connection = connectionFactory.newConnection();
        //3 通过Connection创建一个新的Channel
        Channel channel = connection.createChannel();

        // 这就是一个普通的交换机 和 队列 以及路由
        String exchangeName = "test_dlx_exchange";
        String routingKey = "dlx.#";
        String queueName = "test_dlx_queue";
        channel.exchangeDeclare(exchangeName, "topic", true, false, null);

        Map<String, Object> agruments = new HashMap<String, Object>();
        agruments.put("x-dead-letter-exchange", "dlx.exchange");
        //这个agruments属性,要设置到声明队列上
        channel.queueDeclare(queueName, true, false, false, agruments);
        channel.queueBind(queueName, exchangeName, routingKey);

        //要进行死信队列的声明: dlx.exchange/queue都是由你自己命名的,只不过为了这里只是为了简洁明了而已
        channel.exchangeDeclare("dlx.exchange", "topic", true, false, null);
        channel.queueDeclare("dlx.queue", true, false, false, null);
        channel.queueBind("dlx.queue", "dlx.exchange", "#");

        channel.basicConsume(queueName, true, new MyConsumer(channel));
        log.info("消费端启动成功");
        
    }
}
public class MyConsumer extends DefaultConsumer {

    private static final Logger log = LoggerFactory.getLogger(MyConsumer.class);

    public MyConsumer(Channel channel) {
        super(channel);
    }

    @Override
    public void handleDelivery(String consumerTag, // 消费者标签
            Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        log.info("----dlx--MyConsumer-----consume message----------");
        log.info("consumerTag: " + consumerTag);
        log.info("envelope: " + envelope);
        log.info("properties: " + properties);
        log.info("body: " + new String(body));
    }

}

先把消费端启动,去管控台查看 test_dlx_exchange 以及 test_dlx_queue 这两个普通的交换机、队列, 死信队列 dlx.queue 以及绑定的 dlx.exchange 是否创建成功


image

确认创建成功就关闭消费端,然后再启动生产端,这时候消息没被消费,一直在 test_dlx_queue 中,


image
直到设置的超时时间后,消息就被转发到死信队列中
image

自此,死信队列的简单用法介绍完毕。

相关文章

  • 【深度知识】RabbitMQ死信队列的原理及GO实现

    1. 摘要 本文按照以下目前讲解RabbitMQ死信队列的内容,包括:(1)死信队列是什么?(2)如何配置死信队列...

  • rabbitmq延迟队列

    一、讲解RabbitMQ的的死信队列+ TTL 二、RabbitMQ的延迟队列和应⽤场景 1、简介 2、业界的⼀些...

  • RabbitMQ之认识死信队列一

    前言 RabbitMQ 有个队列叫死信队列,死信队列可以做蛮多事的,比如可以让消息半个小时后消费,规定每天几点钟消...

  • RabbitMQ消息中间件技术精讲17 高级篇十 死信队列

    死信队列介绍 本文是《RabbitMQ精讲系列》中第十七:RabbitMQ消息中间件技术精讲17 高级篇十 死信队...

  • RabbitMQ死信队列

    死信队列介绍 死信队列:DLX(dead-letter-exchange) 利用DLX,当消息在一个队列中变成死信...

  • RabbitMQ死信队列

    什么是死信队列 当发生以下任何事件,那么消息将成为死信 消费者使用basic.reject或 basic.nack...

  • 死信队列 (rabbitMQ)

    转载:http://www.imooc.com/article/283645 1.什么是死信队列 想必有些小伙伴应...

  • RabbitMQ 死信队列

    死信队列 "死信"模式 指的是,当消费者不能处理接收到的消息时,将这个消息重新发布到另外一个队列中,等待重试或者人...

  • RabbitMQ死信队列

    SpringBoot 是为了简化 Spring 应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配的特...

  • rabbitmq 死信队列

    死信队列: DLX,dead-letter-exchange 利用 dlx,当消息在一个队列中变成死信 (dead...

网友评论

    本文标题:rabbitmq 死信队列

    本文链接:https://www.haomeiwen.com/subject/emmdsqtx.html