栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

RabbitMQ之死信队列

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

RabbitMQ之死信队列

文章目录
  • 1. 死信队列概念
  • 2. 消息 TTL 过期
  • 3. 队列达到最大长度
  • 4. 消息被拒

1. 死信队列概念

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

死信来源:

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


2. 消息 TTL 过期

生产者代码:

package cn.edu.xd.five;

import cn.edu.xd.util.RabbitMQUtils;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Producer {
    private static final String NORMAL_EXCHANGE="normal_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel= RabbitMQUtils.getChannerl();
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        //设置消息的TTL时间
        AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().expiration("10000").build();
        for(int i=1;i<=10;i++){
            String msg="info"+i;
            channel.basicPublish(NORMAL_EXCHANGE,"zhangsan",properties,msg.getBytes());
            System.out.println("生产者发送消息:"+msg);
        }
    }
}

消费者1代码。消费者1代码中将正常交换机和死信交换机建立了联系,当正常队列中的消息无法被消费超时时,消息就会被移动到死信队列中

package cn.edu.xd.five;

import cn.edu.xd.util.RabbitMQUtils;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

public class Consumer01 {
    private static final String NORMAL_EXCHANGE="normal_exchange";
    private static final String DEAD_EXCHANGE="dead_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel= RabbitMQUtils.getChannerl();
        //声明死信交换机和普通交换机 类型为 direct
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);

        //声明死信队列
        String deadQueue="dead_queue";
        channel.queueDeclare(deadQueue,false,false,false,null);
        channel.queueBind(deadQueue,DEAD_EXCHANGE,"lisi");

        //声明普通队列
        Map params = new HashMap<>();
        //正常队列设置死信交换机 参数 key 是固定值
        params.put("x-dead-letter-exchange", DEAD_EXCHANGE);
        //正常队列设置死信 routing-key 参数 key 是固定值
        params.put("x-dead-letter-routing-key", "lisi");
        String normalQueue = "normal-queue";
        channel.queueDeclare(normalQueue, false, false, false, params);
        channel.queueBind(normalQueue, NORMAL_EXCHANGE, "zhangsan");


        System.out.println("Consumer01等待接收消息...");
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody());
            System.out.println("Consumer01从Q1接受到的消息:"+message);
        };
        //取消消费的一个回调接口 如在消费的时候队列被删除掉了
        CancelCallback cancelCallback = s -> {
            System.out.println("消息被中断");

        };
       channel.basicConsume(normalQueue,true,deliverCallback,cancelCallback);
    }
}

运行:先运行Consumer1, 然后将其关闭,此时打开web管理界面可以看到产生了两个队列,然后开启Consumer02, 然后再开启Producer, 等待10s钟,消息由正常队列移动到了死信队列中


3. 队列达到最大长度

生产者代码修改:

消费者1代码修改:

运行:启动消费者1,关闭,然后依次启动消费者2和生产者,从运行结果中可以看到消费者2从死信队列中消费了4条消息


4. 消息被拒

生产者代码和3中一样
修改生产者1代码,取消自动应答,并修改为拒绝消息info5, 同时取消3中设置的队列长度为6

运行:启动消费者1,然后启动消费者2,然后启动生产者


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1000339.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号