如果消息发布时没有设置特殊参数:
// 默认情况:无法路由的消息直接被丢弃channel.basicPublish( "my-exchange", // 交换机名称 "routing-key", // 路由键 null, // 消息属性(没有设置mandatory) messageBody // 消息体);
结果:消息被 静默丢弃,生产者不会收到任何通知。
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()
});
});
结果:
这是处理无法路由消息的 最佳实践:
// 1. 首先声明一个备用交换器(通常是一个Fanout类型)channel.assertExchange("my-ae", "fanout", { durable: true });
channel.assertQueue("unroutable-messages",soccer.dj.zuq8.info { 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重要区分:无法路由的消息 不会进入死信队列(DLQ),除非:
| 特性 | 无法路由的消息 | 死信消息 |
|---|---|---|
| 触发时机 | 交换机找不到匹配队列 | 消息在队列中被拒绝、TTL过期、队列超限 |
| 处理方式 | 丢弃/返回/备用交换器 | 转发到死信交换器 |
| 配置位置 | 交换器级别 | 队列级别 |
// 配置备用交换器收集无法路由的订单消息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", gov.gov.rizhi.zuqb.info{
durable: true,
arguments: args
});// 正常队列channel.assertQueue("orders.process", { durable: true });
channel.bindQueue("orders.process", "orders", "order.created");// 生产者发布消息// 如果路由键是 "order.updated"(没有队列绑定)// 消息会进入 dead-letters.orders 队列
生产环境必选方案:
方案一(推荐): 启用备用交换器 + 监控无法路由消息队列方案二: 设置 mandatory=true + 实现ReturnListener
监控和告警:
// 监控无法路由消息队列的长度channel.assertQueue(gov.soccer.cb.zuqzb.info"unroutable-messages", { durable: true });// 定期检查队列消息数const result = channel.checkQueue("unroutable-messages");if (result.messageCount > threshold) { sendAlert("发现大量无法路由的消息!");
}常见原因分析:
RabbitMQ 中无法路由的消息有三条可能的路径:
mandatory=true:返回给生产者处理推荐架构:
生产者 → 主交换器(配置备用交换器) ↓(无法路由) 备用交换器(Fanout) ↓ "unroutable.messages"队列 ↓ 监控系统/人工处理
这样既能保证消息不丢失,又能及时发现路由配置问题。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3107274/ ,如需转载,请注明出处,否则将追究法律责任。