本文是博主在梳理 RabbitMQ 知識的過程中,將所遇到和可能會遇到的基礎知識記錄下來,用作梳理 RabbitMQ 的整體架構和功能的線索文章,通過查找對應的知識能夠快速的了解對應的知識而解決相應的問題。
文章目錄
- 一、RabbitMQ 是什么?
- 二、RabbitMQ 的核心概念
- 01、消息(Message)
- 02、生產者(Producer)
- 03、消費者(Consumer)
- 04、消息中間件的服務節點(Broker)
- 05、隊列(Queue)
- 06、交換機(Exchange)
- 07、路由鍵(RoutingKey)
- 08、綁定(Binding)
- 09、信道(Channel)
- 10、連接(Connection)
- 11、虛擬主機(Virtual Host, vHost)
- 10、多租戶(Multi-Tenancy)
- 11、虛擬主機與多租戶的對比與延伸
- 三、協議與通信
- 1. AMQP 協議(Advanced Message Queuing Protocol)
- 2. MQTT 協議(Message Queuing Telemetry Transport)
- 3. STOMP 協議(Simple Text Oriented Messaging Protocol)
一、RabbitMQ 是什么?
RabbitMQ 是一個開源的消息中間件(Message Broker),基于 AMQP
(高級消息隊列協議,Advanced Message Queuing Protocol)實現,旨在為分布式系統提供可靠的異步通信解決方案。
在開發中引入 RabbitMQ 中間件一般用作不同項目之間的消息傳遞。例如在即時通訊項目中,常會將不同的業務進行構建獨自的服務項目,比如消息服務、文件服務、狀態服務和查詢服務等,各個服務之間相互獨立又彼此相連。例如用戶狀態(上線或下線)的傳遞,實時傳輸到各個服務,而又不會受到其他服務的影響,實現解耦。
- 異步通信橋梁:允許不同應用程序通過
消息
進行間接通信,無需實時同步響應,提升系統解耦性和可擴展性。
使用 RabbitMQ 還有一個好處就是他的消息傳遞是通過交換機傳輸到隊列中,消息隊列具有一定的容量可以應對流量的波動。例如一個大型的即時通訊服務,用戶的狀態會經常發生變化(上線-離開-在線-請勿打擾)等等,例如早晨用戶狀態變化可能會急劇增加,用戶在進入離開狀態會有一段時間,就會出現一個狀態變化的峰值。消息隊列能夠存儲一定的流量,緩解消費者的壓力,同時穩定服務的消費能力不會大幅變化。
- 削峰填谷:通過消息隊列暫存峰值流量,緩解后端服務壓力,適用于流量波動較大的場景(如電商促銷、日志處理)。
狀態服務的消息傳輸是需要穩定傳輸的,不然你就可能會和一個 下線
的人在聊天,這就會影響用戶體驗,基于此,RabbitMQ 具有機制保障消息能夠可靠的傳輸。
- 可靠消息傳遞:支持消息持久化、確認機制(ACK)、重試策略等,確保消息不丟失或重復處理。
此外 RabbitMQ 還具有一些其他優勢,如:
- 多語言支持:提供 Java、Python、C#、Go、JavaScript 等主流語言的客戶端庫,方便跨平臺集成。
- 高可用性與集群:支持節點集群部署(如鏡像隊列),實現故障轉移和負載均衡,保障服務穩定性。
- 插件生態:通過插件擴展功能,例如管理界面(RabbitMQ Management Plugin)、STOMP/MQTT 協議支持、消息追蹤等。
- 輕量與高效:基于 Erlang 語言開發,天生支持高并發和低延遲,適合分布式系統環境。與 Kafka 等吞吐量優先的中間件相比,RabbitMQ 在處理超大規模數據時性能稍弱,更適合中等規模、注重可靠性的業務。
RabbitMQ 是分布式系統中實現異步通信的核心工具,通過消息隊列、交換機和路由規則的組合,幫助開發者解耦系統模塊、提升容錯能力,適用于需要可靠消息傳遞的企業級應用,如金融、電商、物流等領域。
二、RabbitMQ 的核心概念
RabbitMQ 整體上是一個生產者和消費者模型,主要負責接收,存儲和轉發消息。
上圖是從網上找的網圖,標有作者,如有侵權請聯系刪除。
我們可以從該圖了解里面的工作流程:生產者生產消息,攜帶路由鍵發布到交換器中,交換器根據綁定鍵路由到不同的隊列,消費者根據所訂閱的隊列消費消息。
01、消息(Message)
通信的最小單元,通常包含兩個部分:消息體和標簽。
- 消息體:消息體也可以稱之為內容(Payload),實際數據(如 JSON 格式的訂單信息)。
- 標簽:有時被稱為
元數據
,用來表述這條消息。- 例如:路由鍵、過期時間、優先級、是否持久化等。
- 如物流消息:標注
易碎品
(屬性),通知消費者輕拿輕放。
類比:快遞包裹,內部是商品(Payload),外部面單是元數據(地址、重量、保價等)。
02、生產者(Producer)
投遞消息的一方,常見于發送消息的應用程序或服務。
- 不關心消息如何被處理,只負責將消息丟給 RabbitMQ。
- 如打車軟件:司機接單后,將行程信息發送到消息隊列,由后臺系統異步派單。
- 支持批量發送、消息持久化等配置。
類比:餐廳廚師,做好餐后將菜品(消息)交給傳菜員(RabbitMQ),不關心顧客何時就餐。
03、消費者(Consumer)
接收并處理消息的應用程序或服務。當消費者消費一條消息時,只是消費消息的消息體(payload)。在消息路由的過程中,消息的標簽會被丟棄,存入到隊列的只有消息體,消費者也只會消費到消息體,也就不知道消息的生產者是誰。
- 主動
訂閱
隊列,按需拉取消息。- 如電商訂單系統:庫存服務監聽
扣庫存
隊列,收到消息后執行扣減操作。
- 如電商訂單系統:庫存服務監聽
- 支持消息確認(ACK):處理完成后通知 RabbitMQ 移除消息,避免丟失。
類比:超市收銀員,從傳送帶(隊列)上取商品(消息)掃碼結賬,完成后商品離開傳送帶。
04、消息中間件的服務節點(Broker)
在學習 RabbitMQ 時,經常會遇到這個這個概念,英文直譯為中間件(經紀人),一般是消息隊列的服務實體。
對于 RabbitMQ 來說,一個 RabbitMQ Broker 可以簡單的看作一個 RabbitMQ 服務節點,或者 RabbitMQ 服務實例,大多數情況下也可以看作一臺 RabbitMQ 服務器。
05、隊列(Queue)
RabbitMQ 的內部對象,消息的最終存儲容器,消費者從這里獲取消息,可以理解成存放消息的 臨時倉庫
,支持 異步收發
和 削峰填谷
。RabbitMQ 的消息只能存儲在隊列里,和 Kafka 正好相反,Kafka 將消息存儲在 topic (主題)這個層面,而相應的隊列邏輯只是 topic 實際存儲文件中的位移標識。RabbitMQ 最終生產的消息最終會投遞到隊列中,供消費者消費。
- 支持持久化(消息存磁盤,RabbitMQ 重啟不丟失)。
- 多消費者競爭消費(如訂單隊列:多個支付服務節點同時處理訂單,提升吞吐量)。
當多個消費者可以訂閱同一個隊列,這時消息默認會平均分攤(Round-Ronbin,輪詢)給多個消費者進行處理。
- 解耦生產者和消費者(如外賣平臺:商家出餐后將“餐品”放入取餐柜,騎手按需取餐,無需實時等待)。
- 應對流量波動(如電商大促:訂單消息先存入隊列,避免瞬間壓垮支付系統)。
06、交換機(Exchange)
RabbitMQ 最終生產的消息最終會投遞到隊列中,供消費者消費。在這個過程中,消息是先發送到 Exchange 交換器,由交換器將消息根據 路由規則
路由到一個或者多個隊列中。如果路由不到,或許會返還給生產者,也有可能會丟棄消息。
交換器只負責轉發消息,不具備存儲功能,可以理解成一個簡單的實體。交換器有四種不同的類型,不同的類型有不同的類型策略,會在第四章詳細介紹。
- Direct(精準匹配):消息攜帶
路由鍵
,交換機按鍵
路由到對應隊列。 - Fanout(廣播):消息直接復制到所有綁定隊列。
- Topic(模式匹配):支持通配符(如“user.#”匹配“user.register”“user.login”等隊列)。
- headers (頭交換機):不依賴路由鍵的匹配功能,而是根據發送消息中的 headers 屬性進行匹配。
07、路由鍵(RoutingKey)
生產者將消息發送給交換機的時候,一般會指定一個 RoutingKey,用來指定這個消息的路由規則,而這個 RoutingKey 需要與交換器類型和綁定鍵 BindingKey
聯合使用才會生效。
08、綁定(Binding)
RabbitMQ 通過綁定將交換器和隊列關聯起來,在綁定的時候一般會指定一個綁定鍵 BindiingKey
,這樣就知道如何正確的將不同的消息路由到正確的隊列。
整體來說:生產者將消息發給交換器時,需要一個 RoutingKey
,當 BindingKey
和 RoutingKey
相匹配時,消息會被路由到對應隊列中。在綁定多個隊列到一個交換器時,這些綁定允許使用相同的 BindingKey 。
BindingKey 并不是在所有的情況下都生效,它依賴于交換器類型,例如在 fanout 和 header 交換器中就會失效。
- 交換器相當于投遞包裹的郵箱。
- RoutingKey 相當于填寫在包裹上的地址。
- BindingKey 相當于包裹的目的地。
- 在使用綁定的時候,需要的路由鍵是 BindingKey。
- 在發送消息的時候,需要的路由鍵是 RoutingKey。
- 一個交換機可綁定多個隊列,一個隊列可綁定多個交換機。
09、信道(Channel)
生產者和消費者與 RabbitMQ 通信的輕量級通道,復用 TCP 連接。
- 避免頻繁創建 TCP 連接(一個連接可創建多個信道,如 1 個連接支持 1000 個信道,節省資源)。
- 線程安全:每個線程獨立使用信道,互不干擾(如電商訂單服務:10 個線程通過 1 個連接的 10 個信道并發發送消息)。
類比:高速公路的“車道”,多個車輛(消息)通過同一條高速(連接)的不同車道(信道)并行行駛。
10、連接(Connection)
生產者和消費者與 RabbitMQ 建立的TCP 長連接。 其核心生命周期:
- 建立:耗時操作(需認證、協商參數),建議復用。
- 心跳機制:防止連接中斷(默認 60 秒發送一次心跳包)。
- 關閉:異常時自動重連(如網絡閃斷后,消費者重新建立連接繼續消費)。
類比:打電話時的“通話鏈路”,一次撥號(連接)支持多次對話(信道傳輸消息),掛斷后需重新撥號。
11、虛擬主機(Virtual Host, vHost)
虛擬主機是 RabbitMQ 中一種 邏輯隔離機制,類似于操作系統中的
目錄
或數據庫中的Schema
,相當于邏輯隔離的容器
。
它將單個 RabbitMQ 服務器劃分為多個獨立的環境,每個環境擁有自己的 Exchange(交換器)
、Queue(隊列)
、Binding(綁定)
、用戶權限
等資源,且這些資源在不同虛擬主機之間完全隔離(除非顯式共享,通常不會)。
- 資源隔離:每個虛擬主機是一個獨立的沙箱,例如租戶 A 的隊列
order_queue
和租戶 B 的隊列order_queue
互不干擾,因為它們屬于不同虛擬主機。 - 權限控制單元:虛擬主機是 RabbitMQ 權限管理的最小粒度。管理員可為每個虛擬主機單獨配置用戶的 讀/寫/配置權限,例如用戶
user1
只能訪問虛擬主機vhost1
中的隊列,無法查看vhost2
的內容。 - 配置獨立:每個虛擬主機可自定義連接地址(如
amqp://user:password@host:port/vhost1
),甚至支持不同的插件配置(盡管較少使用)。 - 多租戶支持:一個 RabbitMQ 實例可創建多個
vHost
,供不同業務線使用。 - 與物理服務器的關系:虛擬主機是邏輯隔離,而非物理隔離。多個虛擬主機共享 RabbitMQ 服務器的內存、CPU 等資源,但通過權限和命名空間隔離避免數據交叉。
- 與連接(Connection)的關系:客戶端連接時需指定虛擬主機(默認是
/
),一個連接只能屬于一個虛擬主機,無法跨虛擬主機操作資源。 - 與消息路由的關系:Exchange、Queue 的名稱在虛擬主機內唯一,跨虛擬主機可重復,路由規則僅在當前虛擬主機內生效。
10、多租戶(Multi-Tenancy)
多租戶指一個軟件系統為 多個獨立租戶(如企業、團隊、應用) 提供服務,且確保租戶之間的數據、配置、資源相互隔離,同時共享底層基礎設施(降低成本),屬于系統級隔離架構。
核心目標是:
- 隔離性:租戶 A 的數據不能被租戶 B 訪問,故障不擴散。
- 可配置性:每個租戶可自定義參數(如隊列優先級、消息保留策略)。
- 資源效率:共享服務器資源,通過配額管理避免單個租戶耗盡資源。
RabbitMQ 的虛擬主機是實現多租戶的核心機制,二者關系如下:
- 虛擬主機是多租戶的“載體”:每個租戶分配一個獨立虛擬主機,租戶的所有消息實體(隊列、交換器等)均在其中創建,從命名空間和權限上實現隔離。
- 結合權限系統強化隔離:通過
user_tags
(如administrator
、management
)和permission
(配置、讀、寫權限),可精確控制租戶對虛擬主機的操作范圍。例如,租戶 A 的用戶只能 讀 自己虛擬主機的隊列,不能刪除交換器。 - 資源配額補充隔離:雖然虛擬主機本身不提供嚴格的資源限制(如內存、帶寬配額),但可通過 RabbitMQ 的 資源限制插件(如
rabbitmq_shovel
或外部工具) 為不同租戶分配資源上限,避免資源搶占。
與微服務、云架構的結合:
- 微服務多租戶:若微服務架構中不同業務線(如電商的
用戶服務
和訂單服務
)需隔離,可將每個服務分配到獨立虛擬主機,避免隊列名稱沖突或權限泄漏。 - SaaS 應用場景:云服務商為每個客戶(租戶)創建專屬虛擬主機,客戶的消息管道完全獨立,同時共享同一套 RabbitMQ 集群,降低基礎設施成本。
- 多環境隔離:開發、測試、生產環境可使用不同虛擬主機,避免誤操作影響線上環境(如誤刪生產隊列)。
11、虛擬主機與多租戶的對比與延伸
維度 | 虛擬主機(技術實現) | 多租戶(架構目標) |
---|---|---|
定位 | RabbitMQ 內置的邏輯隔離機制,偏技術細節。 | 系統設計目標,關注租戶間的隔離、共享與資源管理。 |
核心價值 | 命名空間隔離、權限控制、連接獨立。 | 支持多租戶的商業模型(如 SaaS),平衡隔離與效率。 |
依賴關系 | 多租戶可通過虛擬主機實現,但還需結合權限、配額等。 | 虛擬主機是多租戶的一種實現方式,非唯一(如通過獨立集群實現)。 |
與其他中間件的對比
- Kafka 的多租戶:通過 Topic(主題)+ ACL(訪問控制列表) 實現,租戶共享集群,但通過 Topic 隔離數據,權限控制更細粒度(如按 Topic 授權),但缺乏類似虛擬主機的“整體隔離容器”。
- RocketMQ 的多租戶:通過 Namespace(命名空間) 實現,與 RabbitMQ 虛擬主機類似,每個 Namespace 包含獨立的 Topic、Group 等資源,支持租戶級隔離。
實踐中的注意事項
- 資源分配均衡:虛擬主機不提供物理隔離,需通過集群節點部署、流量控制等避免單個租戶拖垮整體性能。
- 權限最小化原則:為每個租戶的用戶賬戶分配最小必要權限(如僅
讀
或寫
隊列),防止越權操作。 - 監控與日志分離:通過 RabbitMQ 管理界面或插件(如
rabbitmq_prometheus
)按虛擬主機監控指標(如隊列長度、消息吞吐量),便于租戶級故障排查。 - 跨租戶通信:若需租戶間消息共享,可通過
跨虛擬主機轉發
(如使用 Shovel 插件將消息從一個虛擬主機復制到另一個),但需謹慎設計,避免破壞隔離性。
RabbitMQ 的虛擬主機是實現多租戶的核心技術手段,通過邏輯隔離和權限控制,為多個租戶提供獨立的消息通信空間。二者結合后,既能滿足企業內部多團隊協作的隔離需求,也能支撐云原生時代 SaaS 應用的商業化架構。
理解這兩個概念的關鍵在于把握 隔離與共享的平衡 ——虛擬主機在技術層面提供容器化隔離,多租戶則從架構層面定義了如何利用這種隔離實現高效的資源分配與安全保障。
架構全景圖(結合概念)
生產者 → 連接 → 信道 → 交換機(根據Binding路由)→ 隊列 → 信道 → 消費者 └── 虛擬主機(隔離環境) ── 消息(含元數據)
總結:RabbitMQ 通過這些組件的協作,實現了 生產者無需知道消費者是誰、消費者無需實時等待生產者 的異步通信,是分布式系統解耦的基石。
三、協議與通信
1. AMQP 協議(Advanced Message Queuing Protocol)
AMQP 是一種開放標準的應用層協議,專為面向消息的中間件設計,支持跨平臺、跨語言的企業級消息通信。其核心目標是提供可靠、靈活的消息傳遞機制,適用于復雜的分布式系統。
核心特點:
- 可靠傳輸:支持消息確認(ACK/NACK)、持久化存儲、事務機制,確保消息不丟失。
- 靈活路由:通過交換器(Exchange)、**隊列(Queue)和綁定(Binding)**實現動態消息路由。交換器類型包括:
- 直連(Direct):基于精確的路由鍵匹配。
- 主題(Topic):支持通配符模式匹配路由鍵。
- 扇出(Fanout):廣播到所有綁定隊列。
- 頭部(Headers):基于消息屬性而非路由鍵。
- 多語言支持:兼容多種編程語言(如Java、Python、C#)。
- 協議版本:
- AMQP 0-9-1:廣泛實現(如RabbitMQ),采用傳統的交換器-隊列模型。
- AMQP 1.0:標準化協議,簡化模型,更注重通用消息傳遞(如Apache ActiveMQ支持)。
適用場景:
- 企業應用集成(如銀行交易、訂單處理)。
- 云計算服務(如Azure Service Bus、RabbitMQ)。
- 需要復雜路由和高可靠性的系統。
2. MQTT 協議(Message Queuing Telemetry Transport)
MQTT 是一種輕量級的發布/訂閱模型協議,專為低帶寬、高延遲或不穩定網絡環境設計,廣泛應用于物聯網(IoT)場景。
核心特點:
- 極簡設計:協議頭部僅2字節,減少傳輸開銷。
- QoS分級:
- QoS 0(最多一次):盡力交付,無重傳。
- QoS 1(至少一次):確保消息到達,但可能重復。
- QoS 2(恰好一次):通過四次握手保證精確一次交付。
- 主題層級:支持通配符(
+
單層、#
多層)訂閱,如sensors/+/temperature
。 - 遺囑消息(Last Will):客戶端異常斷開時,代理自動發布預設消息。
- 協議版本:
- MQTT 3.1.1:主流版本,廣泛支持。
- MQTT 5.0:增強功能(如原因碼、共享訂閱、流量控制)。
適用場景:
- 物聯網設備通信(如傳感器數據上報、智能家居控制)。
- 移動應用推送(弱網環境)。
- 需要低功耗和高效傳輸的嵌入式系統。
實現依賴:
在RabbitMQ等中間件中需啟用插件(如 rabbitmq_mqtt
)支持。
3. STOMP 協議(Simple Text Oriented Messaging Protocol)
STOMP 是一種基于文本的簡單協議,設計目標是實現客戶端與消息代理之間的跨語言互操作性,通常結合WebSocket用于瀏覽器通信。
核心特點:
- 文本幀結構:類似HTTP,命令與標頭為純文本,消息體可包含任意格式(如JSON、XML)。
- 示例幀:
SEND destination:/queue/test content-type:text/plainHello, STOMP!
- 示例幀:
- 基礎命令:
CONNECT
/STOMP
:建立連接。SEND
:發送消息到目標(隊列或主題)。SUBSCRIBE
:訂閱目標。ACK
/NACK
:消息確認。
- 簡單性:無內置路由機制,依賴代理的隊列/主題管理。
- 跨平臺性:易于通過Telnet或瀏覽器(WebSocket)調試。
適用場景:
- 瀏覽器實時通信(如股票行情推送、聊天應用)。
- 需要快速原型開發或簡單消息交互的系統。
- 與其他文本協議(如HTTP)集成的場景。
實現依賴:
在RabbitMQ等中間件中需啟用插件(如 rabbitmq_stomp
)支持。
協議對比
特性 | AMQP | MQTT | STOMP |
---|---|---|---|
設計目標 | 企業級可靠消息傳遞 | 輕量級物聯網通信 | 簡單文本交互 |
協議類型 | 二進制 | 二進制 | 文本 |
路由靈活性 | 高(多類型交換器) | 中(基于主題層級) | 低(依賴代理實現) |
QoS/可靠性 | 事務、持久化、ACK機制 | QoS 0/1/2分級 | 基礎ACK支持 |
網絡適應性 | 穩定網絡環境 | 高(適應弱網) | 一般 |
典型應用 | 金融交易、ERP系統 | 傳感器網絡、智能設備 | Web應用、實時儀表盤 |
實現復雜度 | 高 | 中 | 低 |
- AMQP:適合企業級復雜系統,提供靈活路由和高可靠性。
- MQTT:為物聯網優化,輕量且支持弱網環境。
- STOMP:適用于簡單交互場景,尤其是瀏覽器與后端的實時通信。
在RabbitMQ等消息中間件中,AMQP通常為默認支持,而MQTT和STOMP需通過插件啟用。選擇協議時需根據場景需求權衡功能、復雜度與性能。