关于RabbitMQ 中无法路由的消息会去到哪里的问题小结

 更新时间:2026年01月07日 08:47:50   作者:佛祖让我来巡山  
文章主要内容介绍了在RabbitMQ中处理无法路由消息的几种方式,包括默认丢弃、使用mandatory参数返回给生产者、使用备用交换器集中收集和处理,文章还探讨了备用交换器与死信交换器的区别,并提供了一个订单系统的实际工作流程示例,感兴趣的朋友跟随小编一起看看吧

在 RabbitMQ 中,无法路由的消息(即交换机无法将消息路由到任何队列)的处理方式取决于消息发布时的参数配置,主要有以下几种情况:

1. 普通情况(默认行为)

如果消息发布时没有设置特殊参数:

// 默认情况:无法路由的消息直接被丢弃
channel.basicPublish(
  "my-exchange",  // 交换机名称
  "routing-key",  // 路由键
  null,           // 消息属性(没有设置mandatory)
  messageBody     // 消息体
);

结果:消息被静默丢弃,生产者不会收到任何通知。

2. 使用 mandatory 参数

当设置 mandatory=true 时:

channel.basicPublish(
  "my-exchange",
  "unroutable-key",
  { mandatory: true },  // 关键参数
  messageBody
);
// 添加返回监听器
channel.addReturnListener((returnMessage) => {
  console.log("消息无法路由被返回:", {
    replyCode: returnMessage.replyCode,
    replyText: returnMessage.replyText,
    exchange: returnMessage.exchange,
    routingKey: returnMessage.routingKey,
    body: returnMessage.body.toString()
  });
});

结果

  • 消息无法路由时,会通过 Basic.Return 命令返回给生产者
  • 生产者可以监听并处理这些返回的消息
  • 这是推荐的可靠消息发布方式

3. 使用备用交换器(Alternate Exchange,AE)

这是处理无法路由消息的最佳实践

// 1. 首先声明一个备用交换器(通常是一个Fanout类型)
channel.assertExchange("my-ae", "fanout", { durable: true });
channel.assertQueue("unroutable-messages", { durable: true });
channel.bindQueue("unroutable-messages", "my-ae", "");
// 2. 声明主交换器时指定备用交换器
const args = { "alternate-exchange": "my-ae" };
channel.assertExchange("my-direct-exchange", "direct", { 
  durable: true,
  arguments: args  // 设置备用交换器
});

工作原理

发布消息 → 主交换器无法路由 → 自动转发到备用交换器 → 备用交换器路由到专用队列

优点

  • 无需生产者设置 mandatory
  • 所有无法路由的消息都被集中收集
  • 可以后续分析、重试或人工处理

4. 与死信交换器(DLX)的区别

重要区分:无法路由的消息不会进入死信队列(DLQ),除非:

  • 使用备用交换器将消息路由到队列
  • 该队列配置了死信交换器
  • 消息在该队列中过期或被拒绝
特性无法路由的消息死信消息
触发时机交换机找不到匹配队列消息在队列中被拒绝、TTL过期、队列超限
处理方式丢弃/返回/备用交换器转发到死信交换器
配置位置交换器级别队列级别

5. 实际工作流程示例

场景:订单系统

// 配置备用交换器收集无法路由的订单消息
channel.assertExchange("orders-ae", "fanout", { durable: true });
channel.assertQueue("dead-letters.orders", { durable: true });
channel.bindQueue("dead-letters.orders", "orders-ae", "");
// 主交换器
const args = { "alternate-exchange": "orders-ae" };
channel.assertExchange("orders", "direct", { 
  durable: true, 
  arguments: args 
});
// 正常队列
channel.assertQueue("orders.process", { durable: true });
channel.bindQueue("orders.process", "orders", "order.created");
// 生产者发布消息
// 如果路由键是 "order.updated"(没有队列绑定)
// 消息会进入 dead-letters.orders 队列

6. 最佳实践建议

生产环境必选方案:

方案一(推荐):
  启用备用交换器 + 监控无法路由消息队列
方案二:
  设置 mandatory=true + 实现ReturnListener

监控和告警

// 监控无法路由消息队列的长度
channel.assertQueue("unroutable-messages", { durable: true });
// 定期检查队列消息数
const result = channel.checkQueue("unroutable-messages");
if (result.messageCount > threshold) {
  sendAlert("发现大量无法路由的消息!");
}

常见原因分析

路由键拼写错误

消费者队列未正确绑定

交换器类型与路由规则不匹配

动态路由键生成逻辑错误

总结

RabbitMQ 中无法路由的消息有三条可能的路径:

  • 默认:静默丢弃(不推荐)
  • 通过 mandatory=true:返回给生产者处理
  • 通过备用交换器:集中收集到专门队列(最佳实践)

推荐架构

生产者 → 主交换器(配置备用交换器)
                    ↓(无法路由)
                备用交换器(Fanout)
                    ↓
            "unroutable.messages"队列
                    ↓
             监控系统/人工处理

这样既能保证消息不丢失,又能及时发现路由配置问题。

到此这篇关于RabbitMQ 中无法路由的消息会去到哪里?的文章就介绍到这了,更多相关RabbitMQ 无法路由的消息内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Intellij IDEA 2017.3使用Lombok及常用注解介绍

    Intellij IDEA 2017.3使用Lombok及常用注解介绍

    这篇文章主要介绍了Intellij IDEA 2017.3使用Lombok及常用注解介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Spring如何替换掉默认common-logging.jar

    Spring如何替换掉默认common-logging.jar

    这篇文章主要介绍了Spring如何替换掉默认common-logging.jar,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • java String[]字符串数组自动排序的简单实现

    java String[]字符串数组自动排序的简单实现

    下面小编就为大家带来一篇java String[]字符串数组自动排序的简单实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • Java synchronized 锁的 8 个经典问题小结

    Java synchronized 锁的 8 个经典问题小结

    本文通过8个实验探讨Java中synchronized关键字的不同锁机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-02-02
  • windows11下jdk同时安装多个版本并自由切换全网最详细教程

    windows11下jdk同时安装多个版本并自由切换全网最详细教程

    一台电脑可以同时安装多个版本jdk,建议两个,最多不超三个,安装多个JDK版本可能会占用较多的磁盘空间,这篇文章主要介绍了windows11下jdk同时安装多个版本并自由切换的相关资料,需要的朋友可以参考下
    2025-11-11
  • 动态代理模拟实现aop的示例

    动态代理模拟实现aop的示例

    下面小编就为大家带来一篇动态代理模拟实现aop的示例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望对大家有所帮助
    2017-11-11
  • java自动生成ID号的方法

    java自动生成ID号的方法

    这篇文章主要介绍了java自动生成ID号的方法,涉及java生成ID号的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • 使用Mybatis的PageHelper分页工具的教程详解

    使用Mybatis的PageHelper分页工具的教程详解

    这篇文章主要介绍了使用Mybatis的PageHelper分页工具的教程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • MyBatisPlus自定义JsonTypeHandler实现自动转化JSON问题

    MyBatisPlus自定义JsonTypeHandler实现自动转化JSON问题

    这篇文章主要介绍了MyBatisPlus自定义JsonTypeHandler实现自动转化JSON问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Java正则表达式之Pattern和Matcher的使用

    Java正则表达式之Pattern和Matcher的使用

    本文详细介绍了Java中处理正则表达式的Pattern和Matcher类的使用方法和实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-09-09

最新评论