RabbitMQ 知識總結

RabbitMQ知識總結

AMQP協議

AMQP協議是一個提供統一消息服務的應用層標準協議,並不會受到客戶端/中間件不同產品、不同開發語言等條件的影響。RabbitMQ則是基於該協議實現的。

舉個例子來說,如下圖,生產者將消息發送到交換機上,交換機接收到信息以後按照相應的路由鍵路由到隊列中,這裏的交換機只是起到了路由的功能,實際上消息存儲在消息隊列中,接下來在隊列中的的消息可以將其散發到消費者或者消費者主動去獲取消息。

三層協議

該協議分爲三層,分別是Module Layer、Session Layer、Transport Layer,如下圖:

  1. Module Layer:決定基本域模型所產生的行爲,主要定義了一些供客戶端調用的命令,客戶端可以利用這些命令實現自己的業務邏輯。

  2. Session Layer:主要負責將客戶端的命令發送給服務器,再將服務端的應答返回給客戶端,主要爲客戶端和服務器之間通信提供可靠性、同步機制和錯誤處理。

  3. Transport Layer:主要用於二進制數據流的傳輸。

RabbitMQ

我們首先了解一些概念:

  1. Broker:接收和分發消息的應用,像是RabbitMQ、ZeroMQ或者Redis等等。

  2. Connection:publisher/consumer和Broker之間的TCP連接

  3. Channel:兩個AMQP結點之間雙向通信流,通道是多路複用的,因此單個網絡連接可以支撐多個通道,各個通道之間是相互隔離的,其極大的減少了操作系統建立多個TCP連接的開銷。

  4. Message:消息

  5. Exchange:服務器中接收來自生產者程序的消息的實體,並可選擇將這些消息路由到服務器中的消息隊列中

  6. Message queue:保存消息並將它們轉發給消費者

  7. Routing key:一個虛擬地址,虛擬機可用它來確定如何路由一個特定消息

交換機

屬性

交換機常用的屬性有:

  • Name (名稱)

  • Durability (消息代理重啓後,交換機是否還存在)

  • Auto-delete (當所有與此交換機綁定的隊列都不再使用此交換機時是否自動刪除)

類型

Exchange存在多種類型,其中最常使用的包括Direct、Fanout、Topic三種類型,還有一種特殊的Headers,它們分別的用處是:

  1. Direct:Message中的routing key 如果和Binding中的 binding key一致的話,則Exchange會將Message散發到對應的Message queue中。

    在默認的情況下創建的就是該類型的exchange,通常使用在需要發送消息到具體的隊列的情況,比如下面這張圖中,最後交換機會將消息路由到名字爲green的消息隊列中。

  2. Fanout:Exchange會將所有的Message散發到關聯的Message queue中。

    即便是已經提供了routing key,該類型交換機也會忽略掉,並且將消息發送到所有關聯的隊列中,通常用來實現發佈/訂閱模式,比如說體育新聞網站可以用它來近乎實時地將比分更新分發給移動客戶端,分發系統使用它來廣播各種狀態和配置更新等等。

  3. Topic:根據正則表達式將Message散發到匹配的Message queue中。

    比如在下圖中,根據Routing key first.green.fast 能夠匹配到的隊列有.green.和.*.fast,該模式主要用來實現消息多播路由。比如說分發有關於特定地理位置的數據,例如銷售點,涉及到分類或者標籤的新聞更新(例如,針對特定的運動項目或者隊伍)等等。

  4. Headers:類似於Direct,但是當涉及到多個屬性的時候,一個Routing key 無法完全表達,其只能是個字符串,而多屬性需要使用到多個鍵值對錶示,因此使用消息屬性來代替路由鍵作爲路由規則,通過判斷消息頭中的值來和隊列中的值來確定消息的路由位置。

    如果x-match爲any的時候, 表示消息頭的任意一個值被匹配後就可以滿足條件,而當x-match爲 all的時候,表示消息頭的所有的值都需要被匹配到才能滿足條件,比如在下圖中,因爲第一個隊列爲any,並且存在匹配的值,所以可以路由到綠色的路由中,因爲第三個隊列爲all,消息頭並沒有都匹配所有的鍵值對,因此消息只會發送到綠色的消息隊列中。

隊列

同樣的,和交換機一樣,隊列也有常用的屬性:

  • Name (名稱)

  • Durability (消息代理重啓後,交換機是否還存在)

  • Auto-delete (當所有與此交換機綁定的隊列都不再使用此交換機時是否自動刪除)

這裏需要注意的是,如果在消息代理中隊列並不存在,則會根據聲明去定義;如果已經存在,但是這次聲明的隊列的屬性和之前已經存在的屬性存在差異,則會返回一個通道級異常!這裏的持久化設置並不會讓在隊列中的消息也同樣持久化,其只會在消息代理重啓後重新定義該隊列,如果沒有設置消息持久化,那麼隊列中的消息則不會存在。

消息

如果消息無法路由到具體的隊列中,那麼該消息可能會被銷燬或是重新返回給發佈者,這取決於設置的屬性。

消息存在三個動作,分別是確認、拒絕、預取

消息確認

消息確認存在兩種模式,分別是1. 自動確認模式:消息隊列發送完後就銷燬;2.顯示確認模式:在消費者進行確認後再進行銷燬;

在顯示確認模式情況下,如果消費者不幸掛掉了,該機制會使消息重新回到消息隊列中,等待下一位消費者。

拒絕消息

分爲重新放回隊列還是立即銷燬,像是在kombo中,它們分別通過message.requeue()和message.reject()實現。

預取

如果在多個消費者共享一個消息隊列的情況下,可以在消費者發送消息的時候設置預取的消息個數,起到一個負載均衡的效果。

連接和通道

連接即Connection,內部則是通過TCP長連接實現,關閉連接時最好優雅的關閉AMQP連接,即connection.close(),而不是簡單粗暴的關閉TCP連接,否則會報出相關的連接錯誤信息。

如果存在多個連接的情況下,爲了避免創建多個TCP而造成系統資源的浪費和超載,因此使用Channel通道,其本質是共享了TCP的連接,將其連接分爲多個互不影響的連接通道,從而有效的利用TCP連接。

使用

具體參考官方文檔

比較

現在比較流行的消息隊列有ZeroMQ和RabbitMQ,其中ZeroMQ擁有更出色的氫能,不過是建立在允許消息數據丟失的情況下,適用於高吞吐量/低延遲的應用場景中。與ZeroMQ不同,RabbitMQ完全實現了AMQP協議,使用上類似於郵箱服務,支持消息的持久化、事務、擁塞控制、負載均衡等特性,使得RabbitMQ擁有更加廣泛的應用場景。

功能RabbitMQZeroMQ
消息持久化支持不支持
事務支持不支持
類似郵箱socket
性能
穩定性不穩定
支持AMQP協議支持不支持
適用場景不允許數據丟失高吞吐


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章