RabbitMQ死信队列

死信队列

DLX(Dead-Letter-Exchange),当信息在一个队列变成死信(Dead message)后,能被重新发送到DLX中,绑定DLX的队列称之为死信队列。死信队列可以通过检测被拒绝或者未送达的消息来追踪问题。

消息变成死信队列可以是:

  • 消息过期
  • 消息被拒绝,requeue参数为false
  • 队列达到最大长度

下面将介绍导致消息进入死信队列的三种情况

首先创建用于获取Connection对象

package com.dfyang.rabbitmq;

import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.io.IOException;

public class RabbitConnectionFactory {

    private static final String IP_ADDRESS = "192.168.195.150";
    private static final int PORT = 5672;
    private static final String USERNAME = "root";
    private static final String PASSWORD = "151310";

    private static ConnectionFactory factory = new ConnectionFactory();

    static {
        factory.setHost(IP_ADDRESS);
        factory.setPort(PORT);
        factory.setUsername(USERNAME);
        factory.setPassword(PASSWORD);
    }

    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = factory.newConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }
}

(1)消息因超时而进入死信队列

package com.dfyang.rabbitmq.dead;

import com.dfyang.rabbitmq.RabbitConnectionFactory;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.util.HashMap;
import java.util.Map;

public class TimeoutDLX {
    public static void main(String[] args) throws Exception {
        Connection connection = RabbitConnectionFactory.getConnection();
        Channel channel = connection.createChannel();
        //创建DLX及死信队列
        channel.exchangeDeclare("dlx.exchange", "direct");
        channel.queueDeclare("dlx.queue", true, false, false, null);
        channel.queueBind("dlx.queue", "dlx.exchange", "dlx.routingKey");
        //创建测试超时的Exchange及Queue
        channel.exchangeDeclare("timeout.exchange", "direct");
        Map<String, Object> arguments = new HashMap<>();
        //过期时间5s
        arguments.put("x-message-ttl", 5000);
        //绑定DLX
        arguments.put("x-dead-letter-exchange", "exchange.dlx");
        //绑定发送到DLX的RoutingKey
        arguments.put("x-dead-letter-routing-key", "routingKey");
        channel.queueDeclare("timeout.queue", true, false, false, null);
        channel.queueBind("timeout.queue", "timeout.exchange", "timeout.routingKey");
        //发布一条消息
        channel.basicPublish("timeout.exchange", "timeout.routingKey", null, "该消息将在5s后超时".getBytes());
        channel.close();
        connection.close();
    }
}

执行代码
在这里插入图片描述
5s后因超时而进入死心队列
在这里插入图片描述 

(2)消息因被拒绝而进入死信队列

创建生产者,这里将沿用上面的死信队列

package com.dfyang.rabbitmq.dead;

import com.dfyang.rabbitmq.RabbitConnectionFactory;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.util.HashMap;
import java.util.Map;

public class RejectProduct {
    public static void main(String[] args) throws Exception {
        Connection connection = RabbitConnectionFactory.getConnection();
        Channel channel = connection.createChannel();
        //创建测试超时的Exchange及Queue
        channel.exchangeDeclare("reject.exchange", "direct");
        Map<String, Object> arguments = new HashMap<>();
        //绑定DLX
        arguments.put("x-dead-letter-exchange", "dlx.exchange");
        //绑定发送到DLX的RoutingKey
        arguments.put("x-dead-letter-routing-key", "dlx.routingKey");
        channel.queueDeclare("reject.queue", true, false, false, arguments);
        channel.queueBind("reject.queue", "reject.exchange", "reject.routingKey");
        //发布一条消息
        channel.basicPublish("reject.exchange", "reject.routingKey", null, "生产者发送一条消息".getBytes());
        channel.close();
        connection.close();
    }
}

执行一次,reject.queue有一条待消费消息

在这里插入图片描述

拒取一个消息

下面是获取一条消息后拒绝

package com.dfyang.rabbitmq.dead;

import com.dfyang.rabbitmq.RabbitConnectionFactory;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.GetResponse;

public class RejectConsumer {
    public static void main(String[] args) throws Exception {
        Connection connection = RabbitConnectionFactory.getConnection();
        Channel channel = connection.createChannel();
        //获取一条消息,设置为非自动签收
        GetResponse response = channel.basicGet("reject.queue", false);
        //传入消息编号和是否重回队列
        channel.basicReject(response.getEnvelope().getDeliveryTag(), false);
        channel.close();
        connection.close();
    }
}

执行上述代码

还有另一个拒绝方法:channel.basicNack(long deliveryTag, boolean multiple, boolean requeue);
multiple:为false表示拒绝deliveryTag这条消息,为true是表示拒绝deliveryTag之前所有未被当前消费者确认的消息

(3)因队列达到最大长度而进入死信队列

package com.dfyang.rabbitmq.dead;

import com.dfyang.rabbitmq.RabbitConnectionFactory;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

import java.util.HashMap;
import java.util.Map;

public class QueueMaxLengthDLX {
    public static void main(String[] args) throws Exception {
        Connection connection = RabbitConnectionFactory.getConnection();
        Channel channel = connection.createChannel();
        channel.exchangeDeclare("max.exchange", "direct");
        Map<String, Object> arguments = new HashMap<>();
        //设置Queue最大长度为5
        arguments.put("x-max-length", 5);
        //绑定DLX
        arguments.put("x-dead-letter-exchange", "dlx.exchange");
        //绑定发送到DLX的RoutingKey
        arguments.put("x-dead-letter-routing-key", "dlx.routingKey");
        channel.queueDeclare("max.queue", true, false, false, arguments);
        channel.queueBind("max.queue", "max.exchange", "max.routingKey");
        //发布10条消息
        for (int i = 0; i < 10; i++)
            channel.basicPublish("max.exchange", "max.routingKey", null, "发送".getBytes());
        channel.close();
        connection.close();
    }
}

执行上述代码,发现有5条消息被送往了死信队列 

在这里插入图片描述


版权声明:本文为CSDN博主「DFYoung」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dh554112075/article/details/90580067

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值