1 關於消息中間件
1.1 什么是消息中間件?
消息中間件是指在分布式系統中完成消息的發送和接收的基礎軟件。
消息中間件也可以稱消息隊列(Message Queue / MQ),用高效可靠的消息傳遞機制進行與平台無關的數據交流,並基於數據通信來進行分布式系統的集成。通過提供消息傳遞和消息隊列模型,可以在分布式環境下擴展進程的通信。
簡而言之,互聯網場景中經常使用消息中間件進行消息路由、訂閱發布、異步處理等操作,來緩解系統的壓力。
1.2 它解決了我們哪些痛點?
1、解耦: 比如說系統A會交給系統B去處理一些事情,但是A不想直接跟B有關聯,避免耦合太強,就可以通過在A,B中間加入消息隊列,A將要任務的事情交給消息隊列 ,B訂閱消息隊列來執行任務。
這種場景很常見,比如A是訂單系統,B是庫存系統,可以通過消息隊列把削減庫存的工作交予B系統去處理。如果A系統同時想讓B、C、D...多個系統處理問題的時候,這種優勢就更加明顯了。
2、有序性: 先進先出原理,先來先處理,比如一個系統處理某件事需要很長一段時間,但是在處理這件事情時候,有其他人也發出了請求,可以把請求放在消息隊里,一個一個來處理。
對數據的順序性和一致性有強需求的業務,比如同一張銀行卡同時被多個入口使用,需要保證入賬出賬的順序性,避免出現數據不一致。
3、消息路由: 按照不同的規則,將隊列中消息發送到不同的其他隊列中
通過消息隊列將不同染色的請求發送到不同的服務去操作。這樣達成了流量按照業務拆分的目的。
4、異步處理: 處理一項任務的時候,有3個步驟A、B、C,需要先完成A操作, 然后做B、C 操作。任務執行成功與否強依賴A的結果,但不依賴B、C 的結果。
如果我們使用串行的執行方式,那處理任務的周期就會變長,系統的整體吞吐能力也會降低(在同一個系統中做異步其實也是比較大的開銷),所以使用消息隊列是比較好的辦法。
登錄操作就是典型的場景:A:執行登錄並得到結果、B:記錄登錄日志、C:將用戶信息和Token寫入緩存。 執行完A就可以從登錄頁跳到首頁了,B、C讓服務慢慢去消化,不阻塞當前操作。
5、削峰: 將峰值期間的操作削減,比如A同學的整個操作流程包含12個步驟,后續的11個步驟是不需要強關注結果的數據,可以放在消息隊列中。
2 消息中間件的執行原理
2.1 消息中間件的組成
Broker: 消息服務器,作為Server提供消息核心服務
Producer: 消息生產者,業務的發起方,負責生產消息傳輸給broker,
Consumer: 消息消費者,業務的處理方,負責從broker獲取消息並進行業務邏輯處理
Topic: 主題,發布/訂閱模式下的消息統一匯集地,不同生產者向topic發送消息,由MQ服務器分發到不同的訂閱者,實現消息的廣播
Queue: 隊列,PTP模式下,特定生產者向特定queue發送消息,消費者訂閱特定的queue完成指定消息的接收
Message: 消息體,根據不同通信協議定義的固定格式進行編碼的數據包,來封裝業務數據,實現消息的傳輸
這邊以kafka為例子,這是典型的集群模式,Kafka通過Zookeeper管理集群配置,選舉leader,以及在Consumer Group發生變化時進行rebalance。Producer使用push模式將消息發布到broker,Consumer使用pull模式從broker訂閱並消費消息。
- producer 負責生產消息
- consumer 負責消費消息
- broker 消息服務器,提供消息核心的處理工作
- zookeeper 用於生產者和消費者的注冊與發現
2.2 消息中間件的模式分類
2.2.1 PTP點對點
使用queue作為通信載體,消息生產者生產消息發送到queue中,然后消息消費者從queue中取出並且消費消息。
消息被消費以后,queue中不再存儲,所以消息消費者不可能消費到已經被消費的消息。 Queue支持存在多個消費者,但是對一個消息而言,只會有一個消費者可以消費。
點對點模式包含三個角色:
- 消息隊列(Queue)
- 發送者(Sender)
- 接收者(Receiver)
每個消息都被發送到一個特定的隊列,接收者從隊列中獲取消息。隊列保留着消息,可以放在內存 中也可以持久化,直到他們被消費或超時。
特點:
- 每個消息只有一個消費者(Consumer)(即一旦被消費,消息就不再在消息隊列中)
- 發送者和接收者之間在時間上沒有依賴性
- 接收者在成功接收消息之后需向隊列應答成功
- 利用FIFO先進先出的特性,可以保證消息的順序性。
2.2.2 Pub/Sub發布訂閱(廣播)
使用topic作為通信載體,消息生產者(發布)將消息發布到topic中,同時有多個消息消費者(訂閱)消費該消息。和點對點方式不同,發布到topic的消息會被所有訂閱者消費。
queue實現了負載均衡,將producer生產的消息發送到消息隊列中,由多個消費者消費。但一個消息只能被一個消費者接受,當沒有消費者可用時,這個消息會被保存直到有一個可用的消費者。
發布訂閱模型包含三個角色:
- 主題(Topic)
- 發布者(Publisher)
- 訂閱者(Subscriber)
多個發布者將消息發送到Topic,系統將這些消息傳遞給多個訂閱者。
特點:
- 每個消息可以有多個消費者:和點對點方式不同,發布消息可以被所有訂閱者消費
- 發布者和訂閱者之間有時間上的依賴性。
- 針對某個主題(Topic)的訂閱者,它必須創建一個訂閱者之后,才能消費發布者的消息。
- 為了消費消息,訂閱者必須保持運行的狀態。
2.3 消息中間件的優勢
系統解耦:交互系統之間沒有直接的調用關系,只是通過消息傳輸,故系統侵入性不強,耦合度低。
提高系統響應時間:例如原來的一套邏輯,可將緊急重要(需要立刻響應)的業務放到該調用方法中,響應要求不高的使用消息隊列,放到MQ隊列中,供消費者處理。
為大數據處理架構提供服務:通過消息作為整合,大數據的背景下,消息隊列還與實時處理架構整合,為數據處理提供性能支持。
2.4 消息中間件常用協議
AMQP協議、MQTT協議、STOMP協議、XMPP協議、其他基於TCP/IP自定義的協議消息中間件的組成
2.4.1 AMQP
AMQP即Advanced Message Queuing Protocol,是應用層協議的一個開放標准,為面向消息的中間件設計。消息中間件主要用於組件之間的解耦,消息的發送者無需知道消息使用者的存在,反之亦然。AMQP 的主要特征是面向消息、隊列、路由(包括點對點和發布/訂閱)、可靠性、安全。
優點:可靠、通用。
2.4.2 MQTT
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通訊協議,有可能成為物聯網的重要組成部分。該協議支持所有平台,幾乎可以把所有聯網物品和外部連接起來,被用來當做傳感器和致動器(比如通過Twitter讓房屋聯網)的通信協議。
優點:格式簡潔、占用帶寬小、移動端通信、PUSH、嵌入式系統
2.4.3 STOMP
STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息協議,是一種為MOM(Message Oriented Middleware,面向消息的中間件)設計的簡單文本協議。STOMP提供一個可互操作的連接格式,允許客戶端與任意STOMP消息代理(Broker)進行交互。
優點:命令模式(非topic\queue模式)
2.4.4 XMPP
XMPP(可擴展消息處理現場協議,Extensible Messaging and Presence Protocol)是基於可擴展標記語言(XML)的協議,多用於即時消息(IM)以及在線現場探測。適用於服務器之間的准即時操作。核心是基於XML流傳輸,這個協議可能最終允許因特網用戶向因特網上的其他任何人發送即時消息,
即使其操作系統和瀏覽器不同。
優點:通用公開、兼容性強、可擴展、安全性高,但XML編碼格式占用帶寬大
2.5 主流的消息中間件
常見的消息中間件包括:RabbitMQ、RocketMQ、kafka 等,后面我們會有一篇專門對這幾種中間件的能力和技術參數做一項完整的對比,並給出不同業務場景下的技術選型建議。