從 AMQP 到訊息處理過程的介紹
RabbitMQ 是最廣泛使用的開源訊息佇列(Message Queue)之一,基於 AMQP 協定運作:訊息被發送到 Exchange,依據 Binding 規則路由到一個或多個 Queue,再由 Consumer 接收處理並回傳 ACK。本文逐一拆解這些核心元件,包括四種 Exchange 類型的差異,以及訊息堆積時的解決方案。
為什麼要學 RabbitMQ?
學習使用 RabbitMQ 是因為現今的軟體開發領域都會用到 MQ,而 RabbitMQ 作為一款很熱門且被廣泛使用的開源 MQ。透過深入了解 RabbitMQ 一些運作原理,我們可以有效地建立和管理複雜的訊息傳遞系統。
什麼是 AMQP?
AMQP 是一種開放標準的應用層協議,專門設計用於標準化訊息的傳遞和佇列管理。AMQP 的核心設計理念是提供一個統一的、跨平台的訊息傳遞標準。在 AMQP 中,訊息被發送到稱為 Exchanges 的地方,這些 Exchanges 根據定義好的規則將訊息 routing 到一個或多個 Queues。
Exchange 有哪四種類型?
Direct Exchange
這個交換機制是最基本的,也是最簡單的交換機制。它的主要功能是根據 routing key 來決定訊息的分發目的地。在 Direct Exchange 中,當一則訊息發送到該 Exchange 時,它會將這則訊息轉發到與該 Exchange 綁定且 routing key 完全匹配的佇列。
Fanout Exchange
Fanout Exchange 不考慮 routing key,它會將收到的所有訊息廣播到所有訂閱這個 Exchange 的 Queues。這種類型的 Exchange 適合用於廣播場景,如系統通知。因為涉及廣播,效能一定不會比 Direct Exchange 好。
Topic Exchange
為了解決 Fanout Exchange 的一些問題,Topic Exchange 在廣播的概念中也加入了 Direct Exchange 的 routing key 的概念。Topic Exchange 可以使用 routing key pattern match 來跟 Queues 搭配,使用 * 和 # 來達到靈活度。
Header Exchange
Header Exchange 是在訊息的 Header 加入多個 key-value pair 的內容,然後利用 Header 決定要把訊息送到哪些 Queues。可以設定 x-match:any 或 x-match:all,甚至可以設定優先處理程度或訊息內容的機敏程度。
Queue 如何運作?訊息堆積怎麼解?
Queue 是把訊息先進先出處理的儲存容器。每個 Queue 都可以有其特定的屬性,例如 name、durable、exclusive 跟 auto-delete。Queue 會透過 Consumer 發送的 ACK 表達訊息有處理成功,反之如果訊息沒有被正確處理,則會回傳 reject 或是請求訊息重新排隊。
如果訊息的產生速度太快,Consumer 來不及處理完成,就會產生訊息堆積的問題。解決方案包括:設定 Queue 的最大長度、增加 Consumer 數量、改善 Consumer 本身的處理能力、確認有沒有 hot shard 問題、設定 TTL、使用 DLQ (Dead Letter Queue) 來放處理失敗的訊息,以及使用 Exponential Backoff 避免過短的時間重新嘗試。
什麼是 Binding?
Bindings 是定義 Exchange 如何將訊息 routing 到 Queues 的規則。一個 Binding 是一個連接,它定義了從一個 Exchange 到一個 Queue 的路由規則。
Consumer 扮演什麼角色?
在 RabbitMQ 中,消費者(Consumers)就是接收和處理訊息的角色。在 RabbitMQ 中 Queues 是可以被一到多個 Consumers 「訂閱」。Consumers 在訊息正確的接收後會回傳 ACK 給 RabbitMQ。
結論
RabbitMQ 本身的設計有很多為了處理訊息所做的設計,是值得我們參考學習的,可以知道這些設計,推論出要面對哪些可能存在的系統架構。
重點整理
- AMQP 定義了訊息流:Producer → Exchange →(依 Binding 路由)→ Queue → Consumer,以 ACK 確認處理成功。
- 四種 Exchange 各有取捨:Direct 精確匹配 routing key、Fanout 全廣播(效能較差)、Topic 用
*與#做 pattern match、Header 以 key-value 條件路由。 - 訊息堆積的工具箱:限制佇列長度、加 Consumer 或提升處理力、檢查 hot shard、TTL、DLQ、Exponential Backoff。
常見問題
RabbitMQ 的訊息如何從發送到接收?
訊息先發送到 Exchange,Exchange 依據 Binding 定義的路由規則把訊息送進一個或多個 Queue,訂閱該 Queue 的 Consumer 取出處理後回傳 ACK;處理失敗則 reject 或重新排隊。
四種 Exchange 該怎麼選?
一對一精確路由用 Direct;要全體廣播(如系統通知)用 Fanout;需要依主題彈性匹配用 Topic;要用多個條件(key-value)決定路由則用 Header Exchange。
Queue 已經積了幾十萬筆,第一步該做什麼?
先確認是「消化不夠快」還是「有訊息卡住反覆重試」,這兩種的處理方向完全相反。如果 Queue 裡有一小撮訊息一直失敗又被重新排隊,加再多 Consumer 也只是讓它們轉得更快;這種要先把失敗訊息丟進 DLQ,讓正常訊息通過。確認是純粹吞吐不足之後,才輪到加 Consumer 或優化處理邏輯。至於 TTL 與 Queue 最大長度屬於防止雪崩的保險絲,應該在平常就設好,不是等塞爆了才臨時加。

Leave a Reply