前言
當學習完AMQP的基本概念后,可以到http://tryrabbitmq.com/中利用rabbitmq模擬器進行消息的模擬發送和接收
一、什么是AMQP,AMQP與rabbitmq的關系
AMQP(Advanced Message Queue Protocol 高級消息隊列協議):是一個網絡協議,它支持符合條件的客戶端和消息代理中間件(message middleware broker)進行通訊。
rabbitmq是AMQP協議的實現者,所以amqp中的概念和准則也適用於rabbitmq。
二、AMQP基本組成及基本概念
1.組成
AMQP的基本組成如下圖所示,該模型同樣適用於rabbitmq。
基於下圖消息的流向:生產者(publisher/producer)生產具有指定路由鍵(routing key)的消息將其發布給消息代理(broker 即rabbitmq)中的交換機(exchange),交換機將消息中的路由鍵與隊列(queue)綁定信息(binding)中存儲的路由鍵對比,將消息路由到匹配的隊列中。隊列再將信息通過連接(connection)中的通道(channel)推送給訂閱了消息的消費者(consumer)。
2.基本概念
a.生產者(Publisher/Producer):生產者顧名思義就是生產消息的角色。生產者會將消息發送給交換機。為了使交換機正確的將消息路由給隊列,發布消息時需指定消息的路由鍵(routing key)。
b.消息代理(Broker):代理的職能就是接收發布者發布的消息並將消息推送給訂閱了消息的消費者。rabbitmq就相當於一個代理。
c.虛擬主機(Virtual Host):出於多租戶和安全因素設計的,把AMQP的基本組(交換機,隊列,綁定稱為AMQP組件)件划分到一個虛擬的分組中,類似於網絡中的namespace概念。當多個不同的用戶使用同一個borker(RabbitMQ server)提供的服務時,可以划分出多個vhost,每個用戶在自己的vhost創建exchange/queue等。
d.交換機(Exchange):交換機負責接收消息並按照一定的規則將消息路由給隊列。路由的規則存儲在交換機與隊列綁定時指定的routing key。
e.綁定(Binding):交換機和隊列之間通過路由鍵(routing key)相互綁定起來,並根據路由鍵將消息路由到對應隊列。
f.隊列(Queue):消息的載體,exchange中的消息將被路由到隊列中,並推送給消費者或者被消費者取走。
g.連接(Connection):消費者和生產者與消息代理之間的連接
h.通道(Channel):如果消費者每一次從代理中取消息都建立一次連接的話,在消息量大的情況下建立多個連接將會有巨大的開銷。Channel是在Connection內部建立的邏輯連接。如果應用程序支持多線程,可以為每個線程建立單獨的通道進行通訊。AMQP method包含了channel id幫助客戶端和message broker識別channel,所以channel之間是完全隔離的。Channel作為輕量級的Connection極大減少了操作系統建立TCP connection的開銷。
i.消費者(Consumer):接收消息的角色就是消費者
三、交換機
1.交換機的分類
交換機主要分為四種,還有一種比較特殊的默認交換機:
a.直連交換機(direct exchange):將交換機和一個隊列綁定起來,並給該綁定一個路由鍵。當攜帶路由鍵的消息發送給交換機時,交換機會尋找具有匹配的路由鍵的綁定,並將消息路由給對應的隊列。該種交換機為直連交換 機。直連交換機經常用來循環分發任務給多個消費者,此時消息的負載均衡是發生在消費者之間的。
對於下圖而言:當攜帶有orange路由鍵的消息被發送到交換機時,消息會被路由到隊列Q1。
b.主題交換機(topic exchange):將交換機和隊列綁定起來,並給綁定賦予一個模式路由鍵。當攜帶路由鍵的消息發送給交換機時,交換機會尋找具有匹配的模式路由鍵的綁定,並將消息路由給對應的隊列。該種交換機為主題交換機。主題交換機經常用來實現各種分發、訂閱模式及其變種。主題交換機通常用來實現消息的多播路由(multicast routing)。
模式路由鍵routing key一般使用 . 來分隔單詞,而且有兩個通配符可以使用。* 代表任意一個單詞,#代表0個或多個單詞。例如:apple.orange.penaunt,*.orange.*,orange.#。
主題交換機擁有非常廣泛的用戶案例。無論何時,當一個問題涉及到那些想要有針對性的選擇需要接收消息的 多消費者/多應用(multiple consumers/applications) 的時候,主題交換機都可以被列入考慮范圍。
使用案例:
-
- 分發有關於特定地理位置的數據,例如銷售點
- 由多個工作者(workers)完成的后台任務,每個工作者負責處理某些特定的任務
- 股票價格更新(以及其他類型的金融數據更新)
- 涉及到分類或者標簽的新聞更新(例如,針對特定的運動項目或者隊伍)
- 雲端的不同種類服務的協調
- 分布式架構/基於系統的軟件封裝,其中每個構建者僅能處理一個特定的架構或者系統。
對於下圖而言:當攜帶routing key為apple.orange.penanut的消息被發送給交換機時,將會被路由到隊列Q1中。當lazy.apple.pen被發送到交換機時,將會被路由到隊列Q2中。
c.扇形交換機/廣播交換機(fanout exchange):將交換機和任意多個隊列綁定起來,不管綁定上的路由鍵,當消息被發送到交換機上時,消息將會被拷貝並路由到所有綁定到該交換機上的隊列中。
對下圖而言:攜帶任何routing key的消息被發送到交換機上時,消息都將被拷貝並分發到Q1,Q2,Q3中。
扇形交換機的使用的案例:
-
- 大規模多用戶在線(MMO)游戲可以使用它來處理排行榜更新等全局事件
- 體育新聞網站可以用它來近乎實時地將比分更新分發給移動客戶端
- 分發系統使用它來廣播各種狀態和配置更新
- 在群聊的時候,它被用來分發消息給參與群聊的用戶。(AMQP沒有內置presence的概念,因此XMPP可能會是個更好的選擇)
d.頭交換機(header exchange):有時消息的路由操作會涉及到多個屬性,此時使用消息頭就比用路由鍵更容易表達,頭交換機(headers exchange)就是為此而生的。頭交換機使用多個消息屬性來代替路由鍵建立路由規則。通過判斷消息頭的值能否與指定的綁定相匹配來確立路由規則。
我們可以綁定一個隊列到頭交換機上,並給他們之間的綁定使用多個用於匹配的頭(header)。消息代理得從應用開發者那兒取到更多一段信息,換句話說,它需要考慮某條 消息(message)是需要部分匹配還是全部匹配。上邊說的“更多一段消息”就是"x-match"參數。當"x-match"設置為“any”時,消息頭的任意一個值被匹配就可以滿足條件,而當"x-match"設置為“all”的時候,就需要消息頭的所有值都匹配成功。
頭交換機可以視為直連交換機的另一種表現形式。頭交換機能夠像直連交換機一樣工作,不同之處在於頭交換機的路由規則是建立在頭屬性值之上,而不是路由鍵。路由鍵必須是一個字符串,而頭屬性值則沒有這個約束,它們甚至可以是整數或者哈希值(字典)等。頭交換機用的比較少,了解一下概念即可。
當攜帶有{"orange":"apple"}header參數的消息被發送到交換機時,消息將被路由到Q1隊列中。
e.默認交換機(default exchange):默認交換機是一種特殊的直連交換機(direct exchange)。它是由消息代理默認聲明的,該交換機有一個特性,所有新建的隊列都會默認綁定到默認交換機上,並且綁定的routing ke就是隊列的名字。
2.交換機的屬性
除交換機類型外,在聲明交換機時還可以附帶許多其他的屬性,其中最重要的幾個分別是:
-
- Name:交換機名稱。
- Durable:消息代理重啟后,交換機是否還存在。交換機有兩個狀態,持久(durable)、暫存(transient)。持久化的交換機會在消息代理重啟后依舊存在,而暫存的交換機則不會。
- Auto-delete :當所有與之綁定的消息隊列都完成了對此交換機的使用后,刪掉它。
- Arguments:依賴代理本身。
四、隊列
1.隊列屬性
除了隊列名稱,隊列也有另外一些屬性
-
- Name:隊列名,隊列名稱可以自己聲明,也可以由代理來生成。但是自己聲明時,不能聲明以amp.開頭的隊列名,因為這是代理內部使用的隊列名稱格式,如果這樣聲明,將會拋出異常。
- Durable:和交換機一樣,消息代理重啟后,隊列是否還存在
- Exclusive:只被一個連接使用,連接關閉后,將立即刪除隊列。
- Auto-delete:當所有的消費者都退訂隊列后將自動刪除該隊列
五、消費者
1.消息確認
消費者在處理消息的時候偶爾會失敗或者有時會直接崩潰掉。而且網絡原因也有可能引起各種穩日。所以AMQP在什么時候刪除消息才是正確的呢?AMQP規范給了兩種建議:
-
- 當消息代理將消息發送給應用后立即刪除,即自動確認機制。
- 待應用發送一個確認回執(acknowledement)后再刪除消息,即顯示確認模式。
如果一個消費者在尚未發送確認回執的情況下掛掉了,那么AMQP代理會將消息重新投遞給另一個消費者。如果當時沒有可用的消費者了,消息代理會死等下一個注冊到此隊列的消費者,然后再次嘗試投遞。
2.拒絕消息
當一個消費者在收到消息后,由於某種原因導致消息處理失敗,消費者可以告訴消息代理拒絕消息,並指明如何處理這條消息——銷毀它或者重新放入隊列中。
3.預取消息
在多個消費者共享一個隊列的時候,可能會出現有的消費者處理很多消息,而有的消費者沒有消息可處理。此時可以指定在收到下一個確認回執前,消費者一次可以接受的最大消息數。
六、消息屬性和有效載荷
AMQP模型中的消息對象是帶有屬性的。有些屬性及其常見,AMQP中也明確定義了它們,並且開發者們無需費心思思考這些屬性名字所代表的具體含義。例如:
- Content type(內容類型)
- Content encoding(內容編碼)
- Routing key(路由鍵)
- Delivery mode (persistent or not)
投遞模式(持久化 或 非持久化) - Message priority(消息優先權)
- Message publishing timestamp(消息發布的時間戳)
- Expiration period(消息有效期)
- Publisher application id(發布應用的ID)
有些屬性是被AMQP代理所使用的,但是大多數是開放給接收它們的應用解釋器用的。有些屬性是可選的也被稱作消息頭(headers。他們跟HTTP協議的X-Headers很相似。消息屬性需要在消息被發布的時候定義。
消息能夠以持久化的方式發布,AMQP代理會將此消息存儲在磁盤上。如果服務器重啟,系統會確認收到的持久化消息未丟失。簡單地將消息發送給一個持久化的交換機或者路由給一個持久化的隊列,並不會使得此消息具有持久化性質:它完全取決與消息本身的持久模式(persistence mode)。將消息以持久化方式發布時,會對性能造成一定的影響(就像數據庫操作一樣,健壯性的存在必定造成一些性能犧牲)。
參考資料:
https://blog.csdn.net/mx472756841/article/details/50815895
https://blog.csdn.net/whoamiyang/article/details/54954780
https://www.cnblogs.com/frankyou/p/5283539.html
頭交換機用的比較少,了解一下概念即可。