RabbitMQ 死信队列(DLX)

下面给你一套 SpringBoot + RabbitMQ 死信队列(DLX)完整可运行代码,包含:

  • 普通业务队列
  • 死信交换机 + 死信队列
  • 消息过期/拒绝自动进死信
  • 生产者 + 消费者示例

环境:SpringBoot 2.7+/3.x + AMQP Starter


1. pom.xml 依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2. application.yml

yaml 复制代码
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    listener:
      simple:
        acknowledge-mode: manual  # 手动ack

3. RabbitMQ 配置类(核心)

RabbitMQConfig.java

java 复制代码
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 死信队列 DLX 配置
 */
@Configuration
public class RabbitMQConfig {

    // ==================== 死信交换机、队列 ====================
    public static final String DLX_EXCHANGE = "dlx.exchange";
    public static final String DLX_QUEUE = "dlx.queue";
    public static final String DLX_ROUTING_KEY = "dlx.routing.key";

    // 死信交换机
    @Bean
    public DirectExchange dlxExchange() {
        return new DirectExchange(DLX_EXCHANGE);
    }

    // 死信队列
    @Bean
    public Queue dlxQueue() {
        return QueueBuilder.durable(DLX_QUEUE).build();
    }

    // 绑定
    @Bean
    public Binding dlxBinding() {
        return BindingBuilder.bind(dlxQueue())
                .to(dlxExchange())
                .with(DLX_ROUTING_KEY);
    }

    // ==================== 业务普通队列(绑定死信) ====================
    public static final String BUSINESS_EXCHANGE = "business.exchange";
    public static final String BUSINESS_QUEUE = "business.queue";
    public static final String BUSINESS_ROUTING_KEY = "business.routing.key";

    @Bean
    public DirectExchange businessExchange() {
        return new DirectExchange(BUSINESS_EXCHANGE);
    }

    // 业务队列:绑定死信交换机
    @Bean
    public Queue businessQueue() {
        return QueueBuilder.durable(BUSINESS_QUEUE)
                // 死信交换机
                .withArgument("x-dead-letter-exchange", DLX_EXCHANGE)
                // 死信路由key
                .withArgument("x-dead-letter-routing-key", DLX_ROUTING_KEY)
                // 可选:设置队列消息TTL(演示过期进死信)
                // .withArgument("x-message-ttl", 10000)
                .build();
    }

    @Bean
    public Binding businessBinding() {
        return BindingBuilder.bind(businessQueue())
                .to(businessExchange())
                .with(BUSINESS_ROUTING_KEY);
    }
}

4. 生产者(发送消息)

DlxProducer.java

java 复制代码
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import static com.example.config.RabbitMQConfig.*;

@Component
public class DlxProducer {

    @Resource
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送普通消息
     */
    public void sendMsg(String msg) {
        rabbitTemplate.convertAndSend(
                BUSINESS_EXCHANGE,
                BUSINESS_ROUTING_KEY,
                msg
        );
    }

    /**
     * 发送带过期时间的消息(自动进死信)
     */
    public void sendExpireMsg(String msg, int ttl) {
        rabbitTemplate.convertAndSend(
                BUSINESS_EXCHANGE,
                BUSINESS_ROUTING_KEY,
                msg,
                message -> {
                    // 设置消息TTL
                    message.getMessageProperties().setExpiration(String.valueOf(ttl));
                    return message;
                }
        );
    }
}

5. 业务消费者(手动拒绝/失败进死信)

BusinessConsumer.java

java 复制代码
import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import static com.example.config.RabbitMQConfig.BUSINESS_QUEUE;

@Component
public class BusinessConsumer {

    @RabbitListener(queues = BUSINESS_QUEUE)
    public void consume(String msg,
                        Channel channel,
                        @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {

        System.out.println("收到业务消息:" + msg);

        try {
            // 模拟业务异常
            // int i = 1 / 0;

            // 正常确认
            channel.basicAck(tag, false);
            System.out.println("正常消费成功");

        } catch (Exception e) {
            // 拒绝,并且不重回队列 → 进入死信
            channel.basicNack(tag, false, false);
            System.out.println("消费失败,进入死信队列");
        }
    }
}

6. 死信队列消费者

DlxConsumer.java

java 复制代码
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import static com.example.config.RabbitMQConfig.DLX_QUEUE;

@Component
public class DlxConsumer {

    @RabbitListener(queues = DLX_QUEUE)
    public void consumeDlx(String msg) {
        System.err.println("【死信队列收到】:" + msg);
        // 在这里做:重试、记录日志、人工介入、补偿任务
    }
}

7. 测试类

java 复制代码
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;

@SpringBootTest
public class DlxTest {

    @Resource
    private DlxProducer producer;

    @Test
    public void test() {
        // 发送普通消息(消费异常会进死信)
        producer.sendMsg("测试死信消息");

        // 发送5秒过期消息(过期自动进死信)
        // producer.sendExpireMsg("5秒后过期进死信", 5000);
    }
}

8. 消息变成死信的 3 种场景

  1. 消息TTL过期
  2. 消费者 basicNack/reject 且 requeue=false
  3. 队列满了溢出

满足任意一个,都会自动进入你配置的 DLX 死信队列。


相关推荐
Keystone_Onion15 小时前
跨境电商架构演进:基于美国海外仓的中大件分布式仓网路由优化方案
分布式·架构
盛世宏博智慧档案16 小时前
分布式机房环境监测硬件,以太网温湿度采集终端如何应用
分布式·传感器·机房·温湿度
NJCloud18 小时前
ELK企业级日志分析平台(四)——基于 ELFK + Kafka 的日志采集与传输平台部署实践
linux·运维·分布式·elk·kafka
国科安芯18 小时前
星载网络化控制的总线脊梁:四路CANFD在分布式载荷管理中的架构优势
分布式·单片机·嵌入式硬件·架构·系统架构·canfd·低轨卫星星座
Allen_LVyingbo19 小时前
分布式GPU智能算法深度研究2026年版(下)
人工智能·分布式·算法·机器学习·知识图谱
何以解忧,唯有..1 天前
Redisson分布式锁实现原理深度解析
分布式
萧瑟余晖1 天前
Java深入解析篇三十六之分布式系统详解
java·开发语言·分布式
有脚就行2 天前
第30篇-Kubeflow-Training-Operator-K8s上的分布式训练
人工智能·分布式·kubernetes
cc复CC2 天前
从零开始手写 Spark 03|RDD 的惰性流水线
分布式
cc复CC2 天前
从零开始手写 Spark 02|数据流与延迟迭代
大数据·分布式