AMQP,即 高級消息隊列協議(Advanced Message Queuing Protocol),是一個消息中間件應用層協議,用于組件之間的解耦,來提供 統一消息服務。主要功能是 排序消息,路由消息(包括點對點和訂閱-發布),保證消息的可靠性和安全性。
遵循AMPQ協議的客戶端,都能通過 消息中間件 相互通信。這樣 客戶端 就可以采用不同的開發語言實現,彼此無強依賴關系,降低客戶端復雜性,提高開發效率也利于后期維護。
AMQP 的模型架構如下:
- 最左端和最右端,publisher(消息生產者),consumer(消息消費者) 都是客戶端
- 左上方灰色方框為 message消息結構(交換器名exchange_name,路由鍵rountingKey)
- 中間紅色方框為 message broker(消息中間件),如 rabbitMQ,kafka
- 客戶端通過 tcp連接,建立 connection 來進行通信
下面介紹AMQP模型的概念:
1.'pubilsher':消息生產者,生產消息并投送到指定的交換器上。
2.'consumer':消息消費者,從對應的隊列中取出消息消費。
1)當 autoAck 為 true 時,消息發送出去后就認為消費成功,而不管消費者是
否真正消費到這些消息。當channel因意外而關閉,或者消費者在消費過程之
中意外宕機時,會丟失對應的消息。因此這種模式可以提高吞吐量,但存
在數據丟失的風險。
2)當 autoAck 為 false 時,consumer在數據處理完成后需要返回確認信息,
只有broker收到確認消費信息后,才認為這條消息已經被成功處理。
這可以保證數據的可靠性投遞,但會降低系統的吞吐量。
3.'message':消息,由消息頭和消息體組成。消息頭存儲與消息相關的元數據,
如交換器名字(exchange_name),路由鍵(rountingKey)和可選配置(properties),
消息體為實際需要傳遞的數據。
4.'message_broker':消息中間件,如rabbitMQ,kafka。
5.'virtual_host':虛擬主機,類似于linux的namespace,實現用戶資源的隔離
當 broker 有多個用戶時,可以劃分出多個 vhost,每個vhost類似于小型的broker,
擁有獨立的交換器,隊列和綁定關系。用戶根據不同的應用場景選擇vhost。
6.'exchange':交換器,message到達 broker 的第一站。
負責接收publisher的消息并根據綁定關系,將消息路由到到一個或多個queue中
1)當mandatory為true時,如果根據分發規則找不到符合條件的queue,會將消息返回給publisher
2)當mandatory為false時,如果根據綁定關系找不到符合條件的queue,會直接丟棄該message
7.'bindingKey':綁定鍵,exchange和queue通過bindingKey建立綁定關系。
另外還有 'rountingKey'。當publisher將message發送給exchange時,一般會
指定一個 rountingKey,用來指定這個message的路由規則。當rountingKey和
bindingKey基于規則匹配時,消息被路由響應的queue中
8.'queue':消息隊列。存儲路由過來的message,一個queue可以被多個
consumer訂閱,此時queue會通過輪詢(round-robin)方式分發message,即
每條message只會發送給一個consumer,不會出現同一個message被多個
consumer重復消費的情況。
9.'connection':用來傳遞消息的tcp連接
10.'channel':信道。是在connection內部采用 IO多路復用建立的邏輯連接,
每個chanel擁有獨立的channelID,保證channel之間的隔離性,類似于在同一個
tcp連接中建立更小的tcp獨立連接,每次斷開連接,斷開的是channel連接,
最外層的tcp連接并不會斷開,一直在被復用,極大減少了tcp連接的開銷。
基于AMPQ協議實現的rabbitMQ
rabbitMQ是AMQP協議的一個開源實現。架構模型同樣可以用以下的圖來表示:
rabbitMQ具有以下特點:
1. 可靠性,使用一些機制,如持久化,發布確認,傳輸確認等保持可靠性
2. 靈活的路由,提供了多種6工作模式滿足各種業務需求
3. 集群性,多個 rabbitMQ 服務器可以組成一個集群,形成一個邏輯 broker
4. 高可用,queue可以在集群上進行鏡像,使得部分節點出問題仍能保持可用
5. 多種協議,支持多種消息隊列協議,如stomp,mqtt等等
6. 多語言客戶端,幾乎支持所有常用語言,如java,ruby,golang等等
7. 管理界面,提供了一個易用的用戶界面,方便監控和管理
8. 跟蹤機制,如果消息異常,使用者可以找出發生了什么問題
9. 插件機制,提供了許多插件來擴展,也可以編寫自己的插件
下面主要介紹rabbitMQ 6種工作方式:
1. simple模式,如下圖示:
如上圖,simple模式,單個publisher,單個queue,單個consumer
2. work模式,如下圖示:
如上圖,work模式
多個consumer共用一個queue的message
此種模式下,rabbitMQ會自動做負載均衡,將消息輪詢發送給各個消費者,即一個消息只能被一個消費者獲取
3. publish / subscribe 發布訂閱模式(廣播模式),如下圖示:
如上圖,publish / subscribe 發布訂閱模式(廣播模式)
相對前2種模式,多了一個exchange (type為fanout),message先發送到exchange,exchange再分別發送到對應的所有queue。而consumer訂閱自己的queue,在自己訂閱的queue上消費message。
示例應用場景,如下圖示:
比如 網上購物,下單支付成功后,通知用戶的方式有許多種,app推送,短信,email 等等。
message到來后被exchange發送到3個queue(app推送q,短信q,email_q)
之后 app推送服務,短信通知服務,email通知服務 從各自訂閱的queue獲取消息,通知用戶支付成功
4. routing 路由模式,如下圖示:
如上圖示,exchange類型設定為direct
此時 message中的rountingKey 和 exchange中的bindingKey匹配,兩者相等則發送對應的queue中,如果匹配不到bindingKey,則丟棄該message。
示例應用場景,如下圖示:
比如服務產生的日志,日志有許多類型,error,info,debuf等類型的日志,而我們的需求只想要將 error 類型的日志寫入磁盤,就可以用routing模式,將error日志路由到error queue,再由相應的 寫入磁盤服務獲取message,寫入磁盤
5. topic 主題模式,如下圖示:
'*' 和 '#' 代表通配符
'*' 代表匹配 1個單詞(如 "a","abc")
'#' 代表匹配 0個或多個單詞(如 "","a","abc","abc.def.ddd")
exchange 根據 key 模糊匹配到對應的queue
路由鍵為 lazy.orange.hello 的消息會發送給所有隊列;
路由鍵為 quick.orange.fox 的消息只會發送給 Q1 隊列;
路由鍵為 lazy.brown.fox 的消息只會發送給 Q2 隊列;
路由鍵為 lazy.pink.rabbit 的消息只會發送給 Q2 隊列;
路由鍵為 quick.brown.fox 的消息與任何綁定都不匹配;
路由鍵為 orange 或 quick.orange.hello.rabbit 的消息也與任何綁定都不匹配
如上圖示,exchange類型為topic,相對于第4種模式,相同點是都根據 rountingKey 匹配,不同點是 topic 模式支持模糊匹配。
應用場景,比如不同運營商的手機號碼處理不同,可以根據手機號碼的前幾位去做區分,如'185','139'等等