轉自:https://blog.csdn.net/forebe/article/details/117993082
訊息中介軟體相關知識
1、概述
訊息佇列已經逐漸成為企業IT系統內部通訊的核心手段。它具有低耦合、可靠投遞、廣播、流量控制、最終一致性等一系列功能,成為非同步RPC的主要手段之一。當今市面上有很多主流的訊息中介軟體,如老牌的ActiveMQ、RabbitMQ,炙手可熱的Kafka,阿里巴巴自主開發RocketMQ等。
2、訊息中介軟體的組成
2.1 Broker
訊息伺服器,作為server提供訊息核心服務
2.2 Producer
訊息生產者,業務的發起方,負責生產訊息傳輸給broker,
2.3 Consumer
訊息消費者,業務的處理方,負責從broker獲取訊息並進行業務邏輯處理
2.4 Topic
主題,釋出訂閱模式下的訊息統一彙集地,不同生產者向topic傳送訊息,由MQ伺服器分發到不同的訂閱者,實現訊息的 廣播
2.5 Queue
佇列,PTP模式下,特定生產者向特定queue傳送訊息,消費者訂閱特定的queue完成指定訊息的接收
2.6 Message
訊息體,根據不同通訊協議定義的固定格式進行編碼的資料包,來封裝業務資料,實現訊息的傳輸
3 訊息中介軟體模式分類
3.1 點對點
PTP點對點:使用queue作為通訊載體
說明:
訊息生產者生產訊息傳送到queue中,然後訊息消費者從queue中取出並且消費訊息。
訊息被消費以後,queue中不再儲存,所以訊息消費者不可能消費到已經被消費的訊息。 Queue支援存在多個消費者,但是對一個訊息而言,只會有一個消費者可以消費。
3.2 釋出/訂閱
Pub/Sub釋出訂閱(廣播):使用topic作為通訊載體
說明:
訊息生產者(釋出)將訊息釋出到topic中,同時有多個訊息消費者(訂閱)消費該訊息。和點對點方式不同,釋出到topic的訊息會被所有訂閱者消費。
queue實現了負載均衡,將producer生產的訊息傳送到訊息佇列中,由多個消費者消費。但一個訊息只能被一個消費者接受,當沒有消費者可用時,這個訊息會被儲存直到有一個可用的消費者。
topic實現了釋出和訂閱,當你釋出一個訊息,所有訂閱這個topic的服務都能得到這個訊息,所以從1到N個訂閱者都能得到一個訊息的複製。
4 訊息中介軟體的優勢
4.1 系統解耦
互動系統之間沒有直接的呼叫關係,只是透過訊息傳輸,故系統侵入性不強,耦合度低。
4.2 提高系統響應時間
例如原來的一套邏輯,完成支付可能涉及先修改訂單狀態、計算會員積分、通知物流配送幾個邏輯才能完成;透過MQ架構設計,就可將緊急重要(需要立刻響應)的業務放到該呼叫方法中,響應要求不高的使用訊息佇列,放到MQ佇列中,供消費者處理。
4.3 為大資料處理架構提供服務
透過訊息作為整合,大資料的背景下,訊息佇列還與實時處理架構整合,為資料處理提供效能支援。
4.4 Java訊息服務——JMS
Java訊息服務(Java Message Service,JMS)應用程式介面是一個Java平臺中關於面向訊息中介軟體(MOM)的API,用於在兩個應用程式之間,或分散式系統中傳送訊息,進行非同步通訊。
JMS中的P2P和Pub/Sub訊息模式:點對點(point to point, queue)與釋出訂閱(publish/subscribe,topic)最初是由JMS定義的。這兩種模式主要區別或解決的問題就是傳送到佇列的訊息能否重複消費(多訂閱)。
5 訊息中介軟體應用場景
5.1 非同步通訊
有些業務不想也不需要立即處理訊息。訊息佇列提供了非同步處理機制,允許使用者把一個訊息放入佇列,但並不立即處理它。想向佇列中放入多少訊息就放多少,然後在需要的時候再去處理它們。
5.2 解耦
降低工程間的強依賴程度,針對異構系統進行適配。在專案啟動之初來預測將來專案會碰到什麼需求,是極其困難的。透過訊息系統在處理過程中間插入了一個隱含的、基於資料的介面層,兩邊的處理過程都要實現這一介面,當應用發生變化時,可以獨立的擴充套件或修改兩邊的處理過程,只要確保它們遵守同樣的介面約束。
5.3 冗餘
有些情況下,處理資料的過程會失敗。除非資料被持久化,否則將造成丟失。訊息佇列把資料進行持久化直到它們已經被完全處理,透過這一方式規避了資料丟失風險。許多訊息佇列所採用的”插入-獲取-刪除”正規化中,在把一個訊息從佇列中刪除之前,需要你的處理系統明確的指出該訊息已經被處理完畢,從而確保你的資料被安全的儲存直到你使用完畢。
5.4 擴充套件性
因為訊息佇列解耦了你的處理過程,所以增大訊息入隊和處理的頻率是很容易的,只要另外增加處理過程即可。不需要改變程式碼、不需要調節引數。便於分散式擴容。
5.5 過載保護
在訪問量劇增的情況下,應用仍然需要繼續發揮作用,但是這樣的突發流量無法提取預知;如果以為了能處理這類瞬間峰值訪問為標準來投入資源隨時待命無疑是巨大的浪費。使用訊息佇列能夠使關鍵元件頂住突發的訪問壓力,而不會因為突發的超負荷的請求而完全崩潰。
5.6 可恢復性
系統的一部分元件失效時,不會影響到整個系統。訊息佇列降低了程序間的耦合度,所以即使一個處理訊息的程序掛掉,加入佇列中的訊息仍然可以在系統恢復後被處理。
5.7 順序保證
在大多使用場景下,資料處理的順序都很重要。大部分訊息佇列本來就是排序的,並且能保證資料會按照特定的順序來處理。
5.8 緩衝
在任何重要的系統中,都會有需要不同的處理時間的元素。訊息佇列透過一個緩衝層來幫助任務最高效率的執行,該緩衝有助於控制和最佳化資料流經過系統的速度。以調節系統響應時間。
5.9 資料流處理
分散式系統產生的海量資料流,如:業務日誌、監控資料、使用者行為等,針對這些資料流進行實時或批次採集彙總,然後進行大資料分析是當前網際網路的必備技術,透過訊息佇列完成此類資料收集是最好的選擇。
6 訊息中介軟體常用協議
6.1 AMQP協議
AMQP即Advanced Message Queuing Protocol,一個提供統一訊息服務的應用層標準高階訊息佇列協議,是應用層協議的一個開放標準,為面向訊息的中介軟體設計。基於此協議的客戶端與訊息中介軟體可傳遞訊息,並不受客戶端/中介軟體不同產品,不同開發語言等條件的限制。
優點:可靠、通用
6.2 MQTT協議
MQTT(Message Queuing Telemetry Transport,訊息佇列遙測傳輸)是IBM開發的一個即時通訊協議,有可能成為物聯網的重要組成部分。該協議支援所有平臺,幾乎可以把所有聯網物品和外部連線起來,被用來當做感測器和致動器(比如透過Twitter讓房屋聯網)的通訊協議。
優點:格式簡潔、佔用頻寬小、移動端通訊、PUSH、嵌入式系統
6.3 STOMP協議
STOMP(Streaming Text Orientated Message Protocol)是流文字定向訊息協議,是一種為MOM(Message Oriented Middleware,面向訊息的中介軟體)設計的簡單文字協議。STOMP提供一個可互操作的連線格式,允許客戶端與任意STOMP訊息代理(Broker)進行互動。
優點:命令模式(非topic\queue模式)
6.4 XMPP協議
XMPP(可擴充套件訊息處理現場協議,Extensible Messaging and Presence Protocol)是基於可擴充套件標記語言(XML)的協議,多用於即時訊息(IM)以及線上現場探測。適用於伺服器之間的準即時操作。核心是基於XML流傳輸,這個協議可能最終允許因特網使用者向因特網上的其他任何人傳送即時訊息,即使其作業系統和瀏覽器不同。
優點:通用公開、相容性強、可擴充套件、安全性高,但XML編碼格式佔用頻寬大
6.5 其他基於TCP/IP自定義的協議
有些特殊框架(如:redis、kafka、zeroMq等)根據自身需要未嚴格遵循MQ規範,而是基於TCP\IP自行封裝了一套協議,透過網路socket介面進行傳輸,實現了MQ的功能。
7 常見訊息中介軟體MQ介紹
7.1 RocketMQ
阿里系下開源的一款分散式、佇列模型的訊息中介軟體,原名Metaq,3.0版本名稱改為RocketMQ,是阿里參照kafka設計思想使用java實現的一套mq。同時將阿里系內部多款mq產品(Notify、metaq)進行整合,只維護核心功能,去除了所有其他執行時依賴,保證核心功能最簡化,在此基礎上配合阿里上述其他開源產品實現不同場景下mq的架構,目前主要多用於訂單交易系統。
具有以下特點:
- 能夠保證嚴格的訊息順序
- 提供針對訊息的過濾功能
- 提供豐富的訊息拉取模式
- 高效的訂閱者水平擴充套件能力
- 實時的訊息訂閱機制
- 億級訊息堆積能力
官方提供了一些不同於kafka的對比差異:
https://rocketmq.apache.org/docs/motivation/
7.2 RabbitMQ
使用Erlang編寫的一個開源的訊息佇列,本身支援很多的協議:AMQP,XMPP, SMTP,STOMP,也正是如此,使的它變的非常重量級,更適合於企業級的開發。同時實現了Broker架構,核心思想是生產者不會將訊息直接傳送給佇列,訊息在傳送給客戶端時先在中心佇列排隊。對路由(Routing),負載均衡(Load balance)、資料持久化都有很好的支援。多用於進行企業級的ESB整合。
7.3 ActiveMQ
Apache下的一個子專案。使用Java完全支援JMS1.1和J2EE 1.4規範的 JMS Provider實現,少量程式碼就可以高效地實現高階應用場景。可插拔的傳輸協議支援,比如:in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA transports。RabbitMQ、ZeroMQ、ActiveMQ均支援常用的多種語言客戶端 C++、Java、.Net,、Python、 Php、 Ruby等。
7.4 Redis
使用C語言開發的一個Key-Value的NoSQL資料庫,開發維護很活躍,雖然它是一個Key-Value資料庫儲存系統,但它本身支援MQ功能,所以完全可以當做一個輕量級的佇列服務來使用。對於RabbitMQ和Redis的入隊和出隊操作,各執行100萬次,每10萬次記錄一次執行時間。測試資料分為128Bytes、512Bytes、1K和10K四個不同大小的資料。實驗表明:入隊時,當資料比較小時Redis的效能要高於RabbitMQ,而如果資料大小超過了10K,Redis則慢的無法忍受;出隊時,無論資料大小,Redis都表現出非常好的效能,而RabbitMQ的出隊效能則遠低於Redis。
7.5 Kafka
Apache下的一個子專案,使用scala實現的一個高效能分散式Publish/Subscribe訊息佇列系統,具有以下特性:
- 快速持久化:透過磁碟順序讀寫與零複製機制,可以在O(1)的系統開銷下進行訊息持久化;
- 高吞吐:在一臺普通的伺服器上既可以達到10W/s的吞吐速率;
- 高堆積:支援topic下消費者較長時間離線,訊息堆積量大;
- 完全的分散式系統:Broker、Producer、Consumer都原生自動支援分散式,依賴zookeeper自動實現複雜均衡;
- 支援Hadoop資料並行載入:對於像Hadoop的一樣的日誌資料和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。
7.6 ZeroMQ
號稱最快的訊息佇列系統,專門為高吞吐量/低延遲的場景開發,在金融界的應用中經常使用,偏重於實時資料通訊場景。ZMQ能夠實現RabbitMQ不擅長的高階/複雜的佇列,但是開發人員需要自己組合多種技術框架,開發成本高。因此ZeroMQ具有一個獨特的非中介軟體的模式,更像一個socket library,你不需要安裝和執行一個訊息伺服器或中介軟體,因為你的應用程式本身就是使用ZeroMQ API完成邏輯服務的角色。但是ZeroMQ僅提供非永續性的佇列,如果down機,資料將會丟失。如:Twitter的Storm中使用ZeroMQ作為資料流的傳輸。
ZeroMQ套接字是與傳輸層無關的:ZeroMQ套接字對所有傳輸層協議定義了統一的API介面。預設支援 程序內(inproc) ,程序間(IPC) ,多播,TCP協議,在不同的協議之間切換隻要簡單的改變連線字串的字首。可以在任何時候以最小的代價從程序間的本地通訊切換到分散式下的TCP通訊。ZeroMQ在背後處理連線建立,斷開和重連邏輯。
特性:
- 無鎖的佇列模型:對於跨執行緒間的互動(使用者端和session)之間的資料交換通道pipe,採用無鎖的佇列演算法CAS;在pipe的兩端註冊有非同步事件,在讀或者寫訊息到pipe的時,會自動觸發讀寫事件。
- 批次處理的演算法:對於批次的訊息,進行了適應性的最佳化,可以批次的接收和傳送訊息。
- 多核下的執行緒繫結,無須CPU切換:區別於傳統的多執行緒併發模式,訊號量或者臨界區,zeroMQ充分利用多核的優勢,每個核繫結執行一個工作者執行緒,避免多執行緒之間的CPU切換開銷。
ZMQ和kafka、RabbitMQ功能對比
原文連結:https://blog.csdn.net/qq_30264689/article/details/96134059
RabbitMQ是一個AMQP實現,傳統的messaging queue系統實現,基於Erlang。老牌MQ產品了。AMQP協議更多用在企業系統內,對資料一致性、穩定性和可靠性要求很高的場景,對效能和吞吐量還在其次。
Kafka是linkedin開源的MQ系統,主要特點是基於Pull的模式來處理訊息消費,追求高吞吐量,一開始的目的就是用於日誌收集和傳輸,0.8開始支援複製,不支援事務,適合產生大量資料的網際網路服務的資料收集業務。
ZeroMQ只是一個網路程式設計的Pattern庫,將常見的網路請求形式(分組管理,連結管理,釋出訂閱等)模式化、元件化,簡而言之socket之上、MQ之下。對於MQ來說,網路傳輸只是它的一部分,更多需要處理的是訊息儲存、路由、Broker服務發現和查詢、事務、消費模式(ack、重投等)、叢集服務等。
RabbitMQ/Kafka/ZeroMQ 都能提供訊息佇列服務,但有很大的區別。
在面向服務架構中透過訊息代理(比如 RabbitMQ / Kafka等),使用生產者-消費者模式在服務間進行非同步通訊是一種比較好的思想。
因為服務間依賴由強耦合變成了松耦合。訊息代理都會提供持久化機制,在消費者負載高或者掉線的情況下會把訊息儲存起來,不會丟失。就是說生產者和消費者不需要同時線上,這是傳統的請求-應答模式比較難做到的,需要一箇中介軟體來專門做這件事。其次訊息代理可以根據訊息本身做簡單的路由策略,消費者可以根據這個來做負載均衡,業務分離等。
缺點也有,就是需要額外搭建訊息代理叢集(但優點是大於缺點的 ) 。
ZeroMQ 和 RabbitMQ/Kafka 不同,它只是一個非同步訊息庫,在套接字的基礎上提供了類似於訊息代理的機制。使用 ZeroMQ 的話,需要對自己的業務程式碼進行改造,不利於服務解耦。
RabbitMQ 支援 AMQP(二進位制),STOMP(文字),MQTT(二進位制),HTTP(裡面包裝其他協議)等協議。Kafka 使用自己的協議。
Kafka 自身服務和消費者都需要依賴 Zookeeper。
RabbitMQ 在有大量訊息堆積的情況下效能會下降,Kafka不會。畢竟AMQP設計的初衷不是用來持久化海量訊息的,而Kafka一開始是用來處理海量日誌的。
總的來說,RabbitMQ 和 Kafka 都是十分優秀的分散式的訊息代理服務,只要合理部署,不作,基本上可以滿足生產條件下的任何需求。
ZeroMQ,本地程序之間的coordination
RabbitMQ,工作訊息佇列
Kafka, 日誌訂閱,著重資料流處理
處理分散式事務方面,它們哪個更適合呢?是不是可以理解為老牌的RabbitMQ對一致性支援更好好一些!
好像很多公司 用zmq 只是用來方便地做socket,閱讀了 ZMQ 的 Guide 文件後,我的理解是,這是個類似於 Socket 的一系列介面,他跟 Socket 的區別是:普通的 socket 是端到端的(1:1的關係),而 ZMQ 卻是可以N:M 的關係,人們對 BSD 套接字的瞭解較多的是點對點的連線,點對點連線需要顯式地建立連線、銷燬連線、選擇協議(TCP/UDP)和處理錯誤等,而 ZMQ 遮蔽了這些細節,讓你的網路程式設計更為簡單。ZMQ 用於 node 與 node 間的通訊,node 可以是主機或者是程序。
但是的確是浪費了zmq 的很多特性。
RabbitMQ和Kafka基本上是一類東西,各有優劣,ZeroMQ只是一個網路庫,不支援持久化。