作者簡介
Gavin,程式員、軟體架構師、企業架構師,關注智能制造,
本文是專欄《智能制造系統架構》中的文章,其它文章請參閱入坑智能制造系統架構,
訊息佇列是分布式系統中重要的組件,也是企業不同應用系統集成的關鍵中間件,目前常用的Kafka、RabbitMQ、ActiveMQ、ZeroMQ、RocketMQ等都是屬于訊息佇列,而在企業IT架構中,還會使用到服務總線、流處理平臺等技術概念或組件,
本文為你梳理一下訊息佇列是做什么的?何時使用訊息佇列?企業服務總線和流處理平臺和它又是什么關系?希望對你有所幫助,
目錄
什么是佇列
什么是訊息佇列
訊息佇列的優勢
訊息模型——如何發布和獲取訊息
Point-to-Point(PTP)模型
Publisher/Subscriber (Pub/Sub) 模型
何時使用訊息佇列
服務總線
流處理平臺——Kafka
參考資料
什么是佇列
佇列是一種先進先出的資料結構,特殊之處在于它只允許在佇列的前端(front)進行洗掉操作,而在佇列的后端(rear)進行插入操作,

什么是訊息佇列
訊息佇列就是一個佇列結構的中間件,也就是說訊息放入這個中間件之后就可以直接回傳,并不需要系統立即處理,而另外會有一個程式讀取這些資料,并按順序進行逐次處理,
訊息佇列的優勢
訊息佇列的核心功能就是訊息傳遞,但由于其異步性和訊息存盤的特定,使訊息佇列具備如下優勢:
1. 解耦
訊息佇列在處理程序中間插入了一個隱含的、基于資料的介面層,兩邊的處理程序都要實作這一介面,這允許你獨立的擴展或修改兩邊的處理程序,只要確保它們遵守同樣的介面約束,
2. 冗余
有時在處理資料的時候處理程序會失敗,除非資料被持久化,否則將永遠丟失,訊息佇列把資料進行持久化直到它們已經被完全處理,通過這一方式規避了資料丟失風險,在被許多訊息佇列所采用的"插入-獲取-洗掉"范式中,在把一個訊息從佇列中洗掉之前,需要你的處理程序明確的指出該訊息已經被處理完畢,確保你的資料被安全的保存直到你使用完畢,
3. 擴展性
因為訊息佇列解耦了你的處理程序,所以增大訊息入隊和處理的頻率是很容易的;只要另外增加處理程序即可,不需要改變代碼、不需要調節引數,擴展就像調大電力按鈕一樣簡單,
4. 靈活性 & 峰值處理能力
在訪問量劇增的情況下,你的應用仍然需要繼續發揮作用,但是這樣的突發流量并不常見;如果為以能處理這類峰值訪問為標準來投入資源隨時待命無疑是巨大的浪費,使用訊息佇列能夠使關鍵組件頂住增長的訪問壓力,而不是因為超出負荷的請求而完全崩潰,
5. 可恢復性
當體系的一部分組件失效,不會影響到整個系統,訊息佇列降低了行程間的耦合度,所以即使一個處理訊息的行程掛掉,加入佇列中的訊息仍然可以在系統恢復后被處理,而這種允許重試或者延后處理請求的能力通常是造就一個略感不便的用戶和一個沮喪透頂的用戶之間的區別,
6. 送達保證
訊息佇列提供的冗余機制保證了訊息能被實際的處理,只要一個行程讀取了該佇列即可,
7.排序保證
在許多情況下,資料處理的順序都很重要,訊息佇列本來就是排序的,并且能保證資料會按照特定的順序來處理,
8.緩沖
在任何重要的系統中,都會有需要不同的處理時間的元素,例如,加載一張圖片比應用過濾器花費更少的時間,訊息佇列通過一個緩沖層來幫助任務最高效率的執行--寫入佇列的處理會盡可能的快速,而不受從佇列讀的預備處理的約束,該緩沖有助于控制和優化資料流經過系統的速度,
9. 理解資料流
在一個分布式系統里,要得到一個關于用戶操作會用多長時間及其原因的總體印象,是個巨大的挑戰,訊息系列通過訊息被處理的頻率,來方便的輔助確定那些表現不佳的處理程序或領域,這些地方的資料流都不夠優化,
10. 異步通信
很多時候,你不想也不需要立即處理訊息,訊息佇列提供了異步處理機制,允許你把一個訊息放入佇列,但并不立即處理它,你想向佇列中放入多少訊息就放多少,然后在你樂意的時候再去處理它們,
訊息模型——如何發布和獲取訊息
JMS(Java Message Service,Java訊息服務)API是一個訊息服務的標準/規范,允許應用程式組件基于JavaEE平臺創建、發送、接收和讀取訊息,在JMS標準中,有兩種訊息模型:P2P(Point to Point),Publish/Subscribe(Pub/Sub),
Point-to-Point(PTP)模型

在P2P模型中,每個訊息只有一個消費者(即一旦被消費,訊息就不再在訊息佇列中),佇列保留著訊息,直到它們被消費或超時,發送者和接收者之間在時間上沒有依賴性,也就是說當發送者發送了訊息之后,不管接收者有沒有正在運行,它不會影響到訊息被發送到佇列,接收者在成功接收訊息之后需向佇列應答成功如果你希望發送的每個訊息都應該被成功處理的話,那么你需要P2P模型
Publisher/Subscriber (Pub/Sub) 模型
在Pub/Sub模型中包含如下概念:主題(Topic)、發布者(Publisher)、訂閱者(Subscriber),客戶端將訊息發送到主題,多個發布者將訊息發送到Topic,系統將這些訊息傳遞給多個訂閱者,

每個訊息可以有多個消費者,發布者和訂閱者之間有時間上的依賴性,針對某個主題(Topic)的訂閱者,它必須創建一個訂閱之后,才能消費發布者的訊息,而且,為了消費訊息,訂閱者必須保持運行的狀態,當然,為了緩和這種嚴格的時間相關性,JMS允許訂閱者創建一個可持久化的訂閱,這樣,即使訂閱者沒有被激活(運行),它也能接收到發布者的訊息,如果你希望發送的訊息可以不被做任何處理、或者被一個消費者處理、或者可以被多個消費者處理的話,那么可以采用Pub/Sub模型,
何時使用訊息佇列
訊息佇列是軟體系統作資訊傳遞和系統集成的主要手段,同時相對于使用訊息佇列發送訊息而言,還有另外一種更加普遍使用的集成技術,就是API,兩者都具有廣泛的應用,所以在實際架構設計中,經常要考慮的問題是什么時候使用API,什么時候使用訊息佇列,下表列出兩者主要的區別:
| 特征 | API | 訊息佇列 |
|---|---|---|
| 互動特性 | HTTP是同步的,每個請求訊息都會有相應的反饋,從而實作了請求/回應機制, | 訊息是異步的,實作發布/訂閱機制,在該機制下應用系統可以將訊息注冊到定義好的主題上,然后將訊息發布給所有的訂閱者, |
| 應用呼叫 | API 普遍存在,幾乎所有IT基礎設施都會支持HTTP訪問,并且大多數開發語言也會內置支持HTTP, | 需要簡單的應用開發作業,訊息可以幫助你簡化避免訊息丟失的作業,使你能夠能加專注于業務, |
| 耦合性 | 會有一點耦合,因為資訊流會直接從請求方發送到服務提供方, | 完全解耦,訊息佇列扮演了一個臨時快取庫的角色,這樣即使接收訊息的應用或服務器崩潰了,或者過于繁忙無法處理請求,訊息可以在訊息佇列中等待知道服務方可以處理為止, |
如何判斷什么時候該使用API,什么時候該使用訊息呢?舉個例子:
假設一個零售商開放他的產品清單,通過開放這個產品清單,合作廠商可以快速定位到自己的產品,產品清單中的資料是只讀的,所以用戶可以重復的請求訪問,這種場景下,REST API使用簡單并且同步,更適合這個場景,
另一個場景,假設一個醫院要在治療病人之后更新病人的病歷,病歷資訊對于醫院和病人來講都是非常關鍵的資訊,為了保證資訊在傳輸程序中不會丟失,此時采用訊息更加合適,
最后一個場景,假設一個零售商搭建一個應用允許合作廠商訪問他的產品清單并下訂單,這種情況下,可以同時使用API和訊息,在查詢產品清單時,可以使用API,而在下訂單時,為了避免訊息丟失和處理峰值流量,可以使用訊息佇列,
服務總線
訊息總線可以理解成全域的訊息通道,所以相對訊息佇列而言,他的不同之處在于全域性和共享性,所以,訊息總線會包含三部分:通用資料模型、通用指令集和訊息佇列,跟隨SOA(Service Oriented Architecture,面向服務架構)的概念,資訊系統的總線通常叫服務總線,企業層的總線稱之為企業服務總線(ESB),企業服務總線可以看作是一種模式,在這種模式下定義了一個集中式的訊息中間件實作各種后端系統的集成(包括資料模型轉換、連接、路由和編排),從而實作些集成服務可以在構建新應用時復用,
在SOA中,IT架構被分成組件層、Web服務層、業務流程層等,組件層包括各種應用系統,它們通常是技術相關的具體實作,各種具體的分布式組件技術(CORBA、COM/DCOM、J2EE)都可以用于實作組件層的應用組件,通常復雜的IT環境中的組件層都同時使用了多種分布式組件技術,而不同實作技術之間的互聯性障礙給應用集成帶來了極大的困難,進而形成了一個個資訊孤島,SOA引入了Web服務層來解決此種情況下的應用集成問題,Web服務是獨立于各種分布式組件技術的,它使用標準的基于XML的服務描述語言(Web Service Description Language,WSDL)來定義和封裝離散的業務功能,各種支持Web服務的分布式組件技術能夠將其上的業務組件發布成Web服務并產生相應的WSDL檔案,并且只需要依據WSDL描述的資訊就能夠呼叫Web服務,即WSDL所描述的業務功能,在SOA中,需要進入系統集成環節的業務組件都被映射為Web服務,形成了Web服務層,業務流程層則處于Web服務層之上,通過對Web服務的流程編排來實作商業流程,業務流程層通過Web服務層能夠呼叫到基于各種分布式組件技術實作的業務組件,實作了復雜IT系統環境的應用集成,
作為SOA基礎架構的關鍵部分,ESB的功能主要體現在通信、服務互動、應用集成、服務質量、安全性以及管理和監控等方面,在通信方面,ESB能夠支持訊息路由/尋址,支持多種通信技術、通信協議(如JMS、HTTP),支持發布/訂閱的通信模式,能夠處理請求/回應、同步以及異步的訊息傳遞方式,并且要求以可靠的方式傳遞訊息,

常見的ESB產品包括:IBM的WebSphere ESB,Microsoft 基于BizTalk的ESB產品,JBOSS SOA Platform等,
需要強調的是,訊息總線或企業服務總線的目的是為了系統集成和服務共享,因此,當使用訊息總線的時候,所有的服務或者應用必須共享相同的資料型別,指令集以及相同的通信協議,并且在訊息總線中,會最大量訊息轉換和編排的作業,而相對而言,訊息佇列的目的是資訊傳輸,因此并不限制是否型別一致,
流處理平臺——Kafka
市面上的訊息佇列產品有很多,比如ActiveMQ、RabbitMQ 、Kafka 、RocketMQ ,還有 ZeroMQ ,連 redis 這樣的 NoSQL 資料庫也支持 MQ 功能,但其中影響力最大的應該還是Kafka,而從Kafka給自己的定義可以看出,Kafka不只是訊息佇列,而是分布式的流處理平臺,
什么是流處理平臺呢?流處理是一種重要的大資料處理手段,其主要特點是其處理的資料是源源不斷且實時到來的,分布式流處理是一種面向動態資料的細粒度處理模式,基于分布式記憶體,對不斷產生的動態資料進行處理,其對資料處理的快速,高效,低延遲等特性,在大資料處理中發揮越來越重要的作用,流處理技術有很多技術選型,更多資訊可以參考“Apache 的流處理技術概述”,僅從Kafka的角度看流處理平臺和訊息佇列的區別,Kafka作為流處理平臺具有以下三種特性:
- 可以讓你發布和訂閱流式的記錄,這一方面與訊息佇列或者訊息總線類似,
- 可以儲存流式的記錄,并且有較好的容錯性,
- 可以在流式記錄產生時就進行處理,
但與基于佇列和交換的RabbitMQ不同,Kafka的存盤層是使用磁區的事務日志實作的,Kafka還提供用于實時處理流的Streams API和可輕松與各種資料源集成的Connector API,Kafka沒有“執行佇列”的概念,相反,Kafka將記錄的集合存盤在稱為主題(Topic)的類別中,對于每個主題,Kafka維護訊息的磁區日志,每個磁區都是一個有序的,不可變的記錄序列,在該記錄中連續附加訊息,因此Kafka的實作十分適合“Publisher/Subscriber (Pub/Sub) 模型”,但不適合“Point-to-Point(PTP)模型”,因此Kafka的定位并非訊息佇列或訊息總線,而是流處理平臺,
因此,流處理平臺和訊息佇列或訊息總線最大的區別就是在訊息佇列功能基礎上,流處理平臺更加關注對流資料分析的支持,
參考資料
- https://www.gxlcms.com/redis-366754.html
- https://blog.iron.io/top-10-uses-for-message-queue/
- https://developer.ibm.com/articles/introduction-apis-and-messaging/
- https://www.ibm.com/cloud/learn/esb
- https://kafka.apachecn.org/
- https://baike.baidu.com/item/%E4%BC%81%E4%B8%9A%E6%9C%8D%E5%8A%A1%E6%80%BB%E7%BA%BF/8790284?fr=aladdin
- https://www.javatpoint.com/jms-tutorial
- https://baike.baidu.com/item/%E5%88%86%E5%B8%83%E5%BC%8F%E6%B5%81%E5%A4%84%E7%90%86/22729451?fr=aladdin
- https://blog.csdn.net/CSDN_bang/article/details/104454191?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/267502.html
標籤:其他
上一篇:Redis筆記-1(Nosql、Redis基本概念)
下一篇:階段性學習總結
