關(guān)于RabbitMQ?中無法路由的消息會去到哪里的問題小結(jié)
在 RabbitMQ 中,無法路由的消息(即交換機(jī)無法將消息路由到任何隊(duì)列)的處理方式取決于消息發(fā)布時的參數(shù)配置,主要有以下幾種情況:
1. 普通情況(默認(rèn)行為)
如果消息發(fā)布時沒有設(shè)置特殊參數(shù):
// 默認(rèn)情況:無法路由的消息直接被丟棄 channel.basicPublish( "my-exchange", // 交換機(jī)名稱 "routing-key", // 路由鍵 null, // 消息屬性(沒有設(shè)置mandatory) messageBody // 消息體 );
結(jié)果:消息被靜默丟棄,生產(chǎn)者不會收到任何通知。
2. 使用 mandatory 參數(shù)
當(dāng)設(shè)置 mandatory=true 時:
channel.basicPublish(
"my-exchange",
"unroutable-key",
{ mandatory: true }, // 關(guān)鍵參數(shù)
messageBody
);
// 添加返回監(jiān)聽器
channel.addReturnListener((returnMessage) => {
console.log("消息無法路由被返回:", {
replyCode: returnMessage.replyCode,
replyText: returnMessage.replyText,
exchange: returnMessage.exchange,
routingKey: returnMessage.routingKey,
body: returnMessage.body.toString()
});
});結(jié)果:
- 消息無法路由時,會通過 Basic.Return 命令返回給生產(chǎn)者
- 生產(chǎn)者可以監(jiān)聽并處理這些返回的消息
- 這是推薦的可靠消息發(fā)布方式
3. 使用備用交換器(Alternate Exchange,AE)
這是處理無法路由消息的最佳實(shí)踐:
// 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 // 設(shè)置備用交換器
});工作原理:
發(fā)布消息 → 主交換器無法路由 → 自動轉(zhuǎn)發(fā)到備用交換器 → 備用交換器路由到專用隊(duì)列
優(yōu)點(diǎn):
- 無需生產(chǎn)者設(shè)置
mandatory - 所有無法路由的消息都被集中收集
- 可以后續(xù)分析、重試或人工處理
4. 與死信交換器(DLX)的區(qū)別
重要區(qū)分:無法路由的消息不會進(jìn)入死信隊(duì)列(DLQ),除非:
- 使用備用交換器將消息路由到隊(duì)列
- 該隊(duì)列配置了死信交換器
- 消息在該隊(duì)列中過期或被拒絕
| 特性 | 無法路由的消息 | 死信消息 |
|---|---|---|
| 觸發(fā)時機(jī) | 交換機(jī)找不到匹配隊(duì)列 | 消息在隊(duì)列中被拒絕、TTL過期、隊(duì)列超限 |
| 處理方式 | 丟棄/返回/備用交換器 | 轉(zhuǎn)發(fā)到死信交換器 |
| 配置位置 | 交換器級別 | 隊(duì)列級別 |
5. 實(shí)際工作流程示例
場景:訂單系統(tǒng)
// 配置備用交換器收集無法路由的訂單消息
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
});
// 正常隊(duì)列
channel.assertQueue("orders.process", { durable: true });
channel.bindQueue("orders.process", "orders", "order.created");
// 生產(chǎn)者發(fā)布消息
// 如果路由鍵是 "order.updated"(沒有隊(duì)列綁定)
// 消息會進(jìn)入 dead-letters.orders 隊(duì)列6. 最佳實(shí)踐建議
生產(chǎn)環(huán)境必選方案:
方案一(推薦): 啟用備用交換器 + 監(jiān)控?zé)o法路由消息隊(duì)列 方案二: 設(shè)置 mandatory=true + 實(shí)現(xiàn)ReturnListener
監(jiān)控和告警:
// 監(jiān)控?zé)o法路由消息隊(duì)列的長度
channel.assertQueue("unroutable-messages", { durable: true });
// 定期檢查隊(duì)列消息數(shù)
const result = channel.checkQueue("unroutable-messages");
if (result.messageCount > threshold) {
sendAlert("發(fā)現(xiàn)大量無法路由的消息!");
}常見原因分析:
路由鍵拼寫錯誤
消費(fèi)者隊(duì)列未正確綁定
交換器類型與路由規(guī)則不匹配
動態(tài)路由鍵生成邏輯錯誤
總結(jié)
RabbitMQ 中無法路由的消息有三條可能的路徑:
- 默認(rèn):靜默丟棄(不推薦)
- 通過
mandatory=true:返回給生產(chǎn)者處理 - 通過備用交換器:集中收集到專門隊(duì)列(最佳實(shí)踐)
推薦架構(gòu):
生產(chǎn)者 → 主交換器(配置備用交換器)
↓(無法路由)
備用交換器(Fanout)
↓
"unroutable.messages"隊(duì)列
↓
監(jiān)控系統(tǒng)/人工處理
這樣既能保證消息不丟失,又能及時發(fā)現(xiàn)路由配置問題。
到此這篇關(guān)于RabbitMQ 中無法路由的消息會去到哪里?的文章就介紹到這了,更多相關(guān)RabbitMQ 無法路由的消息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Intellij IDEA 2017.3使用Lombok及常用注解介紹
這篇文章主要介紹了Intellij IDEA 2017.3使用Lombok及常用注解介紹,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Spring如何替換掉默認(rèn)common-logging.jar
這篇文章主要介紹了Spring如何替換掉默認(rèn)common-logging.jar,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
java String[]字符串?dāng)?shù)組自動排序的簡單實(shí)現(xiàn)
下面小編就為大家?guī)硪黄猨ava String[]字符串?dāng)?shù)組自動排序的簡單實(shí)現(xiàn)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09
Java synchronized 鎖的 8 個經(jīng)典問題小結(jié)
本文通過8個實(shí)驗(yàn)探討Java中synchronized關(guān)鍵字的不同鎖機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2026-02-02
windows11下jdk同時安裝多個版本并自由切換全網(wǎng)最詳細(xì)教程
一臺電腦可以同時安裝多個版本jdk,建議兩個,最多不超三個,安裝多個JDK版本可能會占用較多的磁盤空間,這篇文章主要介紹了windows11下jdk同時安裝多個版本并自由切換的相關(guān)資料,需要的朋友可以參考下2025-11-11
動態(tài)代理模擬實(shí)現(xiàn)aop的示例
下面小編就為大家?guī)硪黄獎討B(tài)代理模擬實(shí)現(xiàn)aop的示例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望對大家有所幫助2017-11-11
MyBatisPlus自定義JsonTypeHandler實(shí)現(xiàn)自動轉(zhuǎn)化JSON問題
這篇文章主要介紹了MyBatisPlus自定義JsonTypeHandler實(shí)現(xiàn)自動轉(zhuǎn)化JSON問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
Java正則表達(dá)式之Pattern和Matcher的使用
本文詳細(xì)介紹了Java中處理正則表達(dá)式的Pattern和Matcher類的使用方法和實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-09-09

