死信队列

1.死信

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

2.死信来源

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

3.死信流程

4.死信队列实现

4.1 TTL过期

  • 生产者
 public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setUsername("guest");
        factory.setPassword("guest");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.exchangeDeclare("logs", "fanout");
        //死信消息 设置ttl时间
        AMQP.BasicProperties properties =
                new AMQP.BasicProperties()
                        .builder().expiration("10000").build();
       for(int i=0;i<11;i++){
            String message = i + "";
            channel.basicPublish("normal_exchange","zhangsan",null,message.getBytes(StandardCharsets.UTF_8));
        }
    }
  • 消费者1
  public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setUsername("guest");
        factory.setPassword("guest");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        //生明交换机
        channel.exchangeDeclare("normal_exchange", "direct");
        channel.exchangeDeclare("dead_exchange", "direct");

        //声明普通队列
        Map<String, Object> arg = new HashMap<>();
        //过期时间
//        arg.put("x-message-ttl",10000);
        //正常队列设置死信交换机
        arg.put("x-dead-letter-exchange","dead_exchange");
        //设置死信RoutineKey
        arg.put("x-dead-letter-routing-key","lisi");

        //声明队列
        channel.queueDeclare("normal_queue", false,false,false,arg);

        //死信队列
        channel.queueDeclare("dead_queue", false,false,false,null);

        //绑定交换机和队列
        channel.queueBind("normal_queue", "normal_exchange", "zhangsan");
        channel.queueBind("dead_queue", "dead_exchange", "lisi");

        //消息拒绝
        DeliverCallback deliverCallback = (counsumerTag , message) -> {
            System.out.println(new String(message.getBody()));
        };
        CancelCallback cancelCallback = counsumerTag -> {
            System.out.println("消息被中断");
        };

        channel.basicConsume("normal_queue", true, deliverCallback,cancelCallback);
    }
  • 消费者2
 public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setUsername("guest");
        factory.setPassword("guest");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();


        DeliverCallback deliverCallback = (counsumerTag , message) -> {
            System.out.println(new String(message.getBody()));
        };
        CancelCallback cancelCallback = counsumerTag -> {
            System.out.println("消息被中断");
        };
        channel.basicConsume("dead_queue", true, deliverCallback,cancelCallback);
    }

4.2 最大长度

  • 生产者注释掉TTL相关部分
  • 消费者加入
    //设置队列长度限制
    arg.put("x-max-length", 6);

4.3 消息被拒绝

  • 消费者加入
//消息拒绝
        DeliverCallback deliverCallback = (counsumerTag , message) -> {
            String msg = new String(message.getBody(), "UTF-8");
            if(msg.equals("3")){
                System.out.println("拒绝" + msg);
                channel.basicReject(message.getEnvelope().getDeliveryTag(), false);
            } else {
                System.out.println(new String(message.getBody()));
                channel.basicAck(message.getEnvelope().getDeliveryTag(), false);
            }

        };
 //开启手动应答
        channel.basicConsume("normal_queue", false, deliverCallback,cancelCallback);
posted @   lwx_R  阅读(128)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示