RabbitMQ死信队列

死信队列

概念

死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,一般来说,producer 将消息投递到 broker 或者直接到 queue 中,consumer 从 queue 取出消息进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息没有后续的处理,就变成了私信,有死信自然就有了死信队列。

应用场景:为了保证订单业务的消息数据不丢失,需要使用到 RabbitMQ 的死信队列机制,当消息消费发生异常时,将消息投入死信队列中。还有比如说:用户在商城下单成功并点击去支付后在指定时间未支付时自动失效。

来源

消息 TTL 过期

队列达到最大长度(队列满了,无法再添加数据到 mq 中)

消息被拒绝(basic.reject 或 basic.nack) 并且 requeue = false

生产者

package com.my.rabbitmq.seven;
​
import com.my.utils.RabbitMQUtils;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
​
// 死信队列 生产者
public class Producer {
​
    public static final String NORMAL_EXCHANGE = "normal_exchange";
​
    public static void main(String[] args) throws Exception{
        Channel channel = RabbitMQUtils.getChannel();
        // 死信消息 设置TTL时间 time to live 
        // 单位是ms 10000ms = 10s
        AMQP.BasicProperties properties = 
                new AMQP.BasicProperties().builder().expiration("10000").build();
        for (int i = 0; i < 11; i++) {
            String message = "info" + i;
            channel.basicPublish(NORMAL_EXCHANGE, "zhangsan", null, message.getBytes());
        }
    }
    
}

消费者

package com.my.rabbitmq.seven;
​
import com.my.utils.RabbitMQUtils;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
​
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
​
/**
 *  死信队列 实战
 *  消费者1
 */
public class Consumer01 {
    
    // 普通交换机的名称
    public static final String NORMAL_EXCHANGE = "normal_exchange";
    // 死信交换机的名称
    public static final String DEAD_EXCHANGE = "dead_exchange";
    // 普通队列的名称
    public static final String NORMAL_QUEUE = "normal_queue";
    // 死信队列的名称
    public static final String DEAD_QUEUE = "dead_queue";
​
    public static void main(String[] args) throws Exception{
        Channel channel = RabbitMQUtils.getChannel();
        // 声明普通交换机和死信交换机 类型为direct
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);
        
        // 声明普通队列
        Map<String, Object> arguments = new HashMap<>();
        // 过期时间 单位 ms
        //arguments.put("x-message-ttl", 100000);
        // 正常队列设置死信交换机 转发消息到死信队列
        arguments.put("x-dead-letter-exchange", DEAD_EXCHANGE);
        // 设置死信routingKey
        arguments.put("x-dead-letter-routing-key", "lisi");
        // 设置队列最大长度
        arguments.put("x-max-length", 6);
        
        channel.queueDeclare(NORMAL_QUEUE, false, false,false, arguments);
        
        // 声明死信队列
        channel.queueDeclare(DEAD_QUEUE, false, false, false, null);
        
        // 绑定交换机与队列
        channel.queueBind(NORMAL_QUEUE, NORMAL_EXCHANGE, "zhangsan");
        channel.queueBind(DEAD_QUEUE, DEAD_EXCHANGE, "lisi");
        
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("Consumer01接收的消息:" + new String(message.getBody(), "UTF-8"));  
        };
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println(consumerTag + "接收消息失败");
        };
        
        channel.basicConsume(NORMAL_QUEUE, true, deliverCallback, cancelCallback);
        
        
    }
    
}

注意:当达到最大队列长度时,会把队列里面的消息发给死信队列,正常队列中是最新的消息。

package com.my.rabbitmq.seven;
​
import com.my.utils.RabbitMQUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
​
// 消费者
public class Consumer02 {
    
    // 死信队列的名称
    public static final String DEAD_QUEUE = "dead_queue";
​
    public static void main(String[] args) throws Exception{
        Channel channel = RabbitMQUtils.getChannel();
        System.out.println("等待接收消息......");
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("Consumer02接收的消息是:" + new String(message.getBody()));
        };
        channel.basicConsume(DEAD_QUEUE, true, deliverCallback, consumerTag -> {});
    }
​
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值