RabbitMQ-中死信交换机

在RabbitMQ中,死信交换机(DLX,Dead Letter Exchange)是一种用于处理无法正常消费的消息的机制。当消息在一个队列中变成死信(dead letter)之后,它可以被重新发布到另一个交换机,这个交换机就被称为死信交换机。消息变成死信的原因通常有以下几种情况:

  1. 消息被拒绝(Basic.Reject/Basic.Nack)并且设置为不重新入队列。
  2. 消息在队列中的存活时间(TTL)到期。
  3. 队列达到最大长度。

RabbitMQ延迟队列可以通过使用死信交换机和消息的TTL设置来实现。

设置死信交换机和延迟队列

以下是如何使用Java代码来设置死信交换机和延迟队列:

java 复制代码
import com.rabbitmq.client.*;

public class DLXExample {

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        String exchangeName = "dlx_exchange";
        String routingKey = "dlx_routing_key";
        String queueName = "dlx_queue";

        // 声明一个死信交换机
        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC, true);

        // 设置队列的死信交换机属性
        AMQP.Queue.DeclareOk queue = channel.queueDeclare(queueName, true, false, false, Map.of(
                "x-dead-letter-exchange", exchangeName,
                "x-dead-letter-routing-key", routingKey
        ));

        // 绑定队列到死信交换机
        channel.queueBind(queue.getQueue(), exchangeName, routingKey);

        // ...其他业务代码
    }
}

在上述代码中,通过x-dead-letter-exchangex-dead-letter-routing-key参数,我们将队列绑定到了一个死信交换机。当该队列中的消息变为死信时,它们会被发送到这个死信交换机,并根据路由键路由到相应的队列。

为了实现延迟队列的效果,可以设置消息的TTL(Time-To-Live),或者设置队列的TTL。当消息过期后,如果队列设置了死信交换机,消息就会被发送到死信交换机。

发布消息到延迟队列

发布带有TTL的消息到队列:

java 复制代码
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;

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

public class DelayedMessagePublisher {

    public static void main(String[] argv) throws Exception {
        // ...建立连接和通道的代码

        String queueName = "delayed_queue";
        String dlxExchangeName = "dlx_exchange";
        String dlxRoutingKey = "dlx_routing_key";

        // 声明延迟队列,将消息过期后路由到死信交换机
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", dlxExchangeName);
        args.put("x-dead-letter-routing-key", dlxRoutingKey);
        channel.queueDeclare(queueName, true, false, false, args);

        String message = "This is a delayed message";
        AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();

        // 设置消息的TTL
        int ttl = 10000; // 消息的存活时间,单位为毫秒
        builder.expiration(String.valueOf(ttl));
        AMQP.BasicProperties properties = builder.build();

        // 发布消息到延迟队列
        channel.basicPublish("", queueName, properties, message.getBytes());
        System.out.println("Sent message: " + message + " with TTL: " + ttl);

        // ...关闭连接等清理代码
    }
}

在这个例子中,我们设置了消息的TTL属性,并将其发布到了延迟队列。消息过期后,它会自动转发到绑定的死信交换机,然后进入相应的队列。

消费死信队列中的消息

消费来自死信交换机的消息和常规消息消费类似,但是通常这些消息需要特殊处理,因为它们可能代表了失败或者需要延迟处理的情况。

java 复制代码
import com.rabbitmq.client.*;

public class DLXConsumer {

    public static void main(String[] argv) throws Exception {
        // ...建立连接和通道的代码

        String dlxQueueName = "dlx_queue";

        // 启动消费者监听死信队列
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println("Received from DLX: " + message);
            // 确认消息
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        };
        channel.basicConsume(dlxQueueName, false, deliverCallback, consumerTag -> {});

        // ...其他业务代码
    }
}

结合源码

深入源码层面,可以查看RabbitMQ Java客户端库中与队列声明相关的Channel接口方法,比如queueDeclarequeueBind。查看它们如何处理参数,尤其是那些以x-开头的参数,它们通常是用来设置队列的特殊特性,例如死信交换器和消息TTL。

确保消息不丢失并且正确处理,需要理解和利用RabbitMQ提供的各种特性。死信交换机和延迟队列是构建复杂消息系统的有力工具,可以帮助开发者优雅地处理消息失败、延迟和重新调度等场景。在实际应用中,可能需要结合重试逻辑、错误监控和告警系统,以确保系统的稳定性和可靠性。

相关推荐
qq_12498707535 小时前
基于Hadoop的信贷风险评估的数据可视化分析与预测系统的设计与实现(源码+论文+部署+安装)
大数据·人工智能·hadoop·分布式·信息可视化·毕业设计·计算机毕业设计
洛豳枭薰7 小时前
消息队列关键问题描述
kafka·rabbitmq·rocketmq
Coder_Boy_7 小时前
基于Spring AI的分布式在线考试系统-事件处理架构实现方案
人工智能·spring boot·分布式·spring
袁煦丞 cpolar内网穿透实验室8 小时前
远程调试内网 Kafka 不再求运维!cpolar 内网穿透实验室第 791 个成功挑战
运维·分布式·kafka·远程工作·内网穿透·cpolar
人间打气筒(Ada)9 小时前
GlusterFS实现KVM高可用及热迁移
分布式·虚拟化·kvm·高可用·glusterfs·热迁移
xu_yule9 小时前
Redis存储(15)Redis的应用_分布式锁_Lua脚本/Redlock算法
数据库·redis·分布式
難釋懷13 小时前
分布式锁的原子性问题
分布式
ai_xiaogui14 小时前
【开源前瞻】从“咸鱼”到“超级个体”:谈谈 Panelai 分布式子服务器管理系统的设计架构与 UI 演进
服务器·分布式·架构·分布式架构·panelai·开源面板·ai工具开发
凯子坚持 c14 小时前
如何基于 CANN 原生能力,构建一个支持 QoS 感知的 LLM 推理调度器
分布式