【面试题】RabbitMQ 中无法路由的消息会去到哪里?

在 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),除非:

  1. 使用备用交换器将消息路由到队列

  2. 该队列配置了死信交换器

  3. 消息在该队列中过期或被拒绝

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. 最佳实践建议

1.生产环境必选方案

复制代码
方案一(推荐):
  启用备用交换器 + 监控无法路由消息队列

方案二:
  设置 mandatory=true + 实现ReturnListener

2.监控和告警

复制代码
// 监控无法路由消息队列的长度
channel.assertQueue("unroutable-messages", { durable: true });

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

3.常见原因分析

  • 路由键拼写错误

  • 消费者队列未正确绑定

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

  • 动态路由键生成逻辑错误


总结

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

  1. 默认:静默丢弃(不推荐)

  2. 通过 mandatory=true:返回给生产者处理

  3. 通过备用交换器:集中收集到专门队列(最佳实践)

推荐架构

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

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

文章转载自: ++佛祖让我来巡山++

原文链接: https://www.cnblogs.com/sun-10387834/p/19388747

体验地址: http://www.jnpfsoft.com/?from=001YH

相关推荐
海上小飞龙13 小时前
Redis 分布式锁原理:从 SET NX EX 到 Redisson 看门狗
数据库·redis·分布式
明达智控技术14 小时前
国产PLC、远程IO模块在食品包装机的应用
分布式·自动化
YOU OU19 小时前
RabbitMQ应用问题
分布式·rabbitmq
YOU OU1 天前
RabbitMQ高级特性
分布式·rabbitmq
珠***格1 天前
双碳目标下:四可装置如何助力光伏消纳与碳数据上报
网络·人工智能·分布式·安全·边缘计算
科力锐品牌君1 天前
行业龙头|科力锐全链路防勒索 + 多中心容灾方案,构筑河南翔宇医疗业务安全闭环!
网络·数据库·分布式·安全·数据安全·备份
WHS-_-20222 天前
基于网络感知自适应树与辅助路由加速地理分布式机器学习
网络·分布式·机器学习
JLWcai202510092 天前
核电打磨 “安全卫士”|金利威不锈钢专用树脂砂轮,合规高效双在线
mysql·mongodb·eureka·sqlite·rabbitmq·nosql·memcached
Kripath_Rion2 天前
带你速通计算机经典论文(一):分布式系统篇
分布式·后端·架构
ACP广源盛139246256732 天前
Ling‑3.0‑flash 昇腾 0‑Day 适配落地@ACP#IX9104 在国产高密度算力矩阵中的机遇与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件