1. 程式人生 > >消息隊列(一)

消息隊列(一)

ref 方式 通信機制 常常 大量 解耦 art hub 如何

消息隊列MQ

維基百科中是這樣介紹消息隊列的

消息隊列(Message queue)是一種進程間通信或同一進程的不同線程間的通信方式,軟件的貯列用來處理一系列的輸入,通常是來自用戶。消息隊列提供了異步的通信協議,每一個貯列中的紀錄包含詳細說明的數據,包含發生的時間,輸入設備的種類,以及特定的輸入參數,也就是說:消息的發送者和接收者不需要同時與消息隊列交互。消息會保存在隊列中,直到接收者取回它

58沈劍是這樣介紹消息隊列的

消息隊列,是一種跨進程的通信機制,用於上下遊傳遞消息。在互聯網架構中,MQ是一種非常常見的上下遊“邏輯解耦+物理解耦”的消息通信服務。使用MQ後,消息發送上遊只需要依賴MQ,邏輯上和物理上不依賴與下遊。

消息隊列的應用場景

  • 異步處理: 將非核心流程異步化,提高系統響應性能。比如用戶註冊需要發送郵件和短信確認(雖然產品都不會這樣做,僅僅舉例),我們可以在註冊成功後發送消息給MQ,然後郵件服務和短信服務接受消息後執行。這裏,可以直接使用線程完成,但是我們可以使用MQ後,我們不用關心下遊(郵件、短信服務等)有多少任務,並且我們可以簡單的在下遊訂閱上遊即可動態添加。
  • 應用解耦: 將不強依賴於本系統的非核心流程和系統流程進行解耦。比如購買商品後會有積分贈送,這裏積分系統時非核心流程,我們可以讓訂單系統和積分系統解耦。
  • 流量削峰與流控控制: 當上下遊系統處理能力存在差距的時候,利用消息隊列做一個通用的“漏鬥”。在下遊有能力處理的時候,再進行分發。例如,在秒殺系統中我們可以把用戶請求寫入消息隊列中,然後秒殺系統在根據規則依次從消息隊列中取然後進行處理,這樣就不會發送系統由於並發量過大而崩潰。
  • 消息訂閱: 這裏有點像UDP,上遊只關心把消息放入MQ中,下遊誰訂閱了就會獲得消息。
  • 消息通訊: MQ都會內置高效的通信機制,例如我們可以使用MQ作為通信工具進行RPC通信。
  • 日誌處理: 使用MQ解決大量日誌傳輸問題。

日誌處理(轉自新浪是如何分析處理32億條實時日誌的?)
技術分享圖片

電商系統(轉自大型網站架構系列:分布式消息隊列(一))

技術分享圖片

消息隊列的不足

  • 系統更加復雜,多了MQ組件
  • 消息可靠性和重復性互為矛盾,消息不丟不重難以同時保證
  • 上遊無法知道下遊的執行結果

調用方實時依賴執行結果的業務場景,使用調用,而不是MQ

消息隊列的消息協議

常見的MQ有RabbitMQ、ActiveMQ、Kafka、RocketMQ等等,它們支持不同的通信協議.例如AMQP、SMTP、STOMP、HTTP等等,下面是一下協議介紹。

AMQP

AMQP(高級消息隊列協議)是應用層網絡協議,它支持符合要求的客戶端應用和消息中間件代理之間通信。

技術分享圖片

AMQP協議的各個部分

  • AMQP協議中的元素包括:Message(消息體)、Producer(生產者)、Consumer(消費者)、Virtual Host(虛擬節點)、Exchange(交換機)、Queue(隊列)等
  • 由Producer(消息生產者)和Consumer(消息消費者)構成了AMQP的客戶端,他們是發送消息和接收消息的主體。AMQP服務端稱為Broker,一個Broker中一定包含完整的Virtual Host(虛擬主機)、 Exchange(交換機)、Queue(隊列)定義
  • 一個Broker可以創建多個Virtual Host(虛擬主機),我們將討論的Exchange和Queue都是虛擬機中的工作元素(還有User元素)。註意,如果AMQP是由多個Broker構成的集群提供服務,那麽一個Virtual Host也可以由多個Broker共同構成
  • Connection是由Producer(消息生產者)和Consumer(消息消費者)創建的連接,連接到Broker物理節點上。但是有了Connection後客戶端還不能和服務器通信,在Connection之上客戶端會創建Channel,連接到Virtual Host或者Queue上,這樣客戶端才能向Exchange發送消息或者從Queue接受消息。一個Connection上允許存在多個Channel,只有Channel中能夠發送/接受消息
  • Exchange元素是AMQP協議中的交換機,Exchange可以綁定多個Queue也可以同時綁定其他Exchange。消息通過Exchange時,會按照Exchange中設置的Routing(路由)規則,將消息發送到符合的Queue或者Exchange中

AMQP中消息的交互

  1. 在Producer(消息生產者)客戶端建立了Channel後,就建立了到Broker上Virtual Host的連接。接下來Producer就可以向這個Virtual Host中的Exchange發送消息了
  2. Exchange(交換機)能夠處理消息的前提是:它至少已經和某個Queue或者另外的Exchange形成了綁定關系,並設置好了到這些Queue和Excahnge的Routing(路由規則)。Exchange中的Routing有三種模式,在Exchange收到消息後,會根據設置的Routing(路由規則),將消息發送到符合要求的Queue或者Exchange中(路由規則還會和Message中的Routing Key屬性配合使用)
  3. Queue收到消息後,可能會進行如下的處理:如果當前沒有Consumer的Channel連接到這個Queue,那麽Queue將會把這條消息進行存儲直到有Channel被創建(AMQP協議的不同實現產品中,存儲方式又不盡相同);如果已經有Channel連接到這個Queue,那麽消息將會按順序被發送給這個Channel
  4. Consumer收到消息後,就可以進行消息的處理了。但是整個消息傳遞的過程還沒有完成:視設置情況,Consumer在完成某一條消息的處理後,將需要手動的發送一條ACK消息給對應的Queue(當然您可以設置為自動發送,或者無需發送)。Queue在收到這條ACK信息後,才會認為這條消息處理成功,並將這條消息從Queue中移除;如果在對應的Channel斷開後,Queue都沒有這條消息的ACK信息,這條消息將會重新被發送給另外的Channel。當然,您還可以發送NACK信息,這樣這條消息將會立即歸隊,並發送給另外的Channel

AMQP協議中的Message

AMQP協議的消息格式如下:

技術分享圖片

其中內容在PAYLOAD部分,PAYLOAD部分格式如下:

技術分享圖片

關於AMQP更加詳細的資料見於:AMQP官網、關於AMQP網友的博客

STOMP

STOMP(簡單文本定向協議)同樣是應用層協議,它提供一個可交互操作的連接格式,容許STOMP客戶端和任意STOMP消息代理(Broker)進行交互,常用於消息中間件。STOMP協議基於幀(Frame)進行通信,第一行包含命令,然後緊跟鍵值對形式的Header內容,第二行空行,第三行開始就是Body內容,末尾都以空字符結尾。

STOMP消息格式和HTTP請求很像,格式如下:

COMMAD
header1:value1
header2:value2
...

Body

常見幀命令有:

  • CONNECT
  • SEND
  • SUBSCRIBE
  • UNSUBSCRIBE
  • ACK
  • NACK
  • ...

例如STOMPSEND消息:

SEND
destination:/app/hello
content-length:20

{"message":"World!"}

關於STOMP資料見於:STOMP1.2官方規範、關於STOMP網友的博客

JMS

JMS(Java消息服務)不是網絡協議,其是Java關於消息服務提供了一組通用接口,具體實現的協議由使用該接口的應用程序實現。在MQ中ActiveMQ、RocketMQ都實現了該協議。

這裏有篇介紹JMS文章:JMS學習一(JMS介紹)

Reference

http://blog.csdn.net/u012758088/article/details/78024581
https://www.cnblogs.com/my_life/articles/7002138.html
https://www.jianshu.com/p/cee941ca0c09
架構師之路工作號《到底什麽時候該使用MQ?》(由於微信公眾號文章URL有時間限制,所以沒有列出來)

消息隊列(一)