RabbitMQ死信队列

RabbitMQ死信队列

死信,就是指那些无法被消费的消息,一般来说,producer 将消息投递到 broker 或者直接到 queue 里了,consumer 从 queue 取出消息进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列。
应用场景:为了保证订单业务的消息数据不丢失,需要使用到 RabbitMQ 的死信队列机制,当消息消费发生异常时,将消息投入死信队列中.还有比如说: 用户在商城下单成功并点击去支付后在指定时间未支付时自动失效。

死信的来源
1.消息 TTL 过期
2.队列达到最大长度(队列满了,无法再添加数据到 mq 中)
3.消息被拒绝(basic.reject 或 basic.nack)并且 requeue=false

在这里插入图片描述

生产者代码

public class DeadProducer {

    public static final String NORMAL_EXCHANGE = "normal_exchange";

    public static final String NORMAL_QUEUE = "normal_queue";

    public static final String ROUTING_KEY_NORMAL = "nobody_jack";

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {

        Channel channel = RabbitMqUtils.getChannel();
        
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        //设置属性 当消息超过指定时间未被消费,则进入死信队列
        AMQP.BasicProperties properties = new AMQP.BasicProperties()
        .builder().expiration("10000").build();
        channel.confirmSelect();
        for(int i = 0; i <= 10; i++){
            String msg = "test"+i;
            boolean flag = channel.waitForConfirms();
            if(flag){
                System.out.println("消息发送完成:"+msg);
            }
            channel.basicPublish(NORMAL_EXCHANGE,ROUTING_KEY_NORMAL,properties,msg.getBytes(StandardCharsets.UTF_8));
        }
    }
}

消费者1

public class DeadQueueConsumer1 {

    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 final String ROUTING_KEY_NORMAL = "nobody_jack";

    public static final String ROUTING_KEY_DEAD = "bitch";


    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtils.getChannel();
        //声明交换机
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);

        //设置死信队列进入的参数
        Map<String,Object> params = new HashMap<>();
        //设置交换机
        params.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        //设置routingKey
        params.put("x-dead-letter-routing-key",ROUTING_KEY_DEAD);
        //超时时间
//        params.put("x-message-ttl",10000);
        //设置队列长度
        params.put("x-max-length",8);

        //声明普通队列
        channel.queueDeclare(NORMAL_QUEUE,false,false,false,params);
        channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,ROUTING_KEY_NORMAL);

        //声明死信队列
        channel.queueDeclare(DEAD_QUEUE,false,false,false,null);
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,ROUTING_KEY_DEAD);

        System.out.println("队列1等待接收消息");
        //消息回调
        DeliverCallback deliverCallback = (consumerTag,  message) -> {
            try {
                Thread.sleep(11000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String msg = new String(message.getBody(),"UTF-8");
            System.out.println("普通队列的消息:"+msg);
            //设置应答
            channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
        };

        channel.basicConsume(NORMAL_QUEUE,false,deliverCallback, consumerTag -> {

        });
    }
}

消费者2 消费私信队列消息

public class DeadQueueConsumer2 {

    public static final String DEAD_EXCHANGE = "dead_exchange";

    public static final String DEAD_QUEUE = "dead_queue";

    public static final String ROUTING_KEY_DEAD = "bitch";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtils.getChannel();
        //声明交换机
        channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);

        //声明死信队列
        channel.queueDeclare(DEAD_QUEUE,false,false,false,null);
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,ROUTING_KEY_DEAD);

        System.out.println("队列2等待接收消息");
        DeliverCallback deliverCallback = (consumerTag,  message) -> {
            String msg = new String(message.getBody(),"UTF-8");
            System.out.println("死信队列的消息:"+msg);
            channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
        };
        channel.basicConsume(DEAD_QUEUE,false,deliverCallback, consumerTag -> {

        });
    }
}

分别启动生产者和消费者1 消费者2

消费者1运行的过程中关闭服务
在这里插入图片描述
等待10秒后由死信队列2接收
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值