RabbitMQ-死信队列

RabbitMQ-死信队列

一、产生来源

死信队列(Dead Letter Queue, DLQ)是消息队列中的一种特殊机制。正常情况下,消息会被直接消费,但由于以下几个原因,消息可能会被转移到死信队列中:

  • 消息被拒绝(basic.rejectbasic.nack)并且不重回队列。
  • 消息在队列中超时(TTL, Time-To-Live)。
  • 队列长度限制已达到上限,无法再存储新消息。

死信队列的主要作用是用来处理那些无法被正常消费的消息,确保系统的健壮性。

二、实战

架构图

RabbitMQ-死信队列_第1张图片

如上图所示,正常的消息会进入C1消费者进行处理,但由于某些原因(例如超时、拒绝等),部分消息被转入了死信队列,并最终由C2消费者进行处理。

代码展示

Consumer1:正常消息消费者
package com.lucifer.rabbitmq.DeadLetterQueue;

import com.lucifer.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

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

public class Consumer1 {
    public static final String normal_exchange = "normal_exchange0";
    public static final String dead_exchange = "dead_exchange0";
    public static final String normal_queue = "normal_queue0";
    public static final String dead_queue = "dead_queue0";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();

        // 声明交换机
        channel.exchangeDeclare(normal_exchange, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(dead_exchange, BuiltinExchangeType.DIRECT);

        // 声明队列并设置参数
        Map<String, Object> arguments = new HashMap<>();
        // 设置死信交换机
        arguments.put("x-dead-letter-exchange", dead_exchange);
        // 设置死信路由键
        arguments.put("x-dead-letter-routing-key", "lisi");
        // 设置消息TTL(过期时间为10秒)
        arguments.put("x-message-ttl", 10000);

        // 声明正常队列
        channel.queueDeclare(normal_queue, false, false, false, arguments);
        // 声明死信队列
        channel.queueDeclare(dead_queue, false, false, false, null);

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

        System.out.println("等待接收消息...");

        // 消费消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("Consumer1 接收到的消息:" + new String(message.getBody()));
        };
        channel.basicConsume(normal_queue, true, deliverCallback, consumerTag -> {});
    }
}
Consumer2:死信队列消息消费者
package com.lucifer.rabbitmq.DeadLetterQueue;

import com.lucifer.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class Consumer2 {
    public static final String dead_queue = "dead_queue0";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("等待接收死信消息...");

        // 消费死信队列消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println("Consumer2 接收到的死信消息:" + new String(message.getBody()));
        };
        channel.basicConsume(dead_queue, true, deliverCallback, consumerTag -> {});
    }
}
Producer:生产者发送消息
package com.lucifer.rabbitmq.DeadLetterQueue;

import com.lucifer.rabbitmq.utils.RabbitMqUtils;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;

public class Producer {
    public static final String normal_exchange = "normal_exchange0";
    public static final String dead_exchange = "dead_exchange0";
    public static final String normal_queue = "normal_queue0";
    public static final String dead_queue = "dead_queue0";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();

        // 设置10秒的TTL(过期时间)
        AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().expiration("10000").build();

        // 发送10条消息
        for (int i = 0; i < 10; i++) {
            String message = "info" + i;
            channel.basicPublish(normal_exchange, "zhangsan", properties, message.getBytes());
            System.out.println("发送消息:" + message);
        }
    }
}

代码解释

  • Consumer1:从normal_queue0队列中消费消息,该队列设置了一个死信交换机和路由键。当消息超时后会转入死信队列。
  • Consumer2:从dead_queue0死信队列中消费死信消息。
  • Producer:向normal_exchange0发送消息,并指定消息的TTL(10秒),当消息在规定时间内没有被消费时,会被转入死信队列。

通过这套机制,可以有效处理那些在业务逻辑中无法正常消费的消息。

你可能感兴趣的:(rabbitmq,ruby,分布式)