Java分佈式系統---消息中間件

@(Java消息中間件)java

簡介

消息中間件也能夠稱消息隊列,是指用高效可靠的消息傳遞機制進行與平臺無關的數據交流,並基於數據通訊來進行分佈式系統的集成。經過提供消息傳遞和消息隊列模型,能夠在分佈式環境下擴展進程的通訊。當下主流的消息中間件有RabbitMQ、Kafka、ActiveMQ、RocketMQ等。其能在不一樣平臺之間進行通訊,經常使用來屏蔽各類平臺協議之間的特性,實現應用程序之間的協同。其優勢在於可以在客戶端和服務器之間進行同步和異步的鏈接,而且在任什麼時候刻均可以將消息進行傳送和轉發。是分佈式系統中很是重要的組件,主要用來解決應用耦合、異步通訊、流量削峯等問題redis

消息中間件的做用

消息中間件幾大主要做用以下:算法

  • 解耦
    下降工程間的強依賴程度,針對異構系統進行適配。在項目啓動之初來預測未來項目會碰到什麼需求,是極其困難的。經過消息系統在處理過程當中間插入了一個隱含的、基於數據的接口層,兩邊的處理過程都要實現這一接口,當應用發生變化時,能夠獨立的擴展或修改兩邊的處理過程,只要確保它們遵照一樣的接口約束。
  • 冗餘(存儲)
    有些狀況下,處理數據的過程會失敗。除非數據被持久化,不然將形成丟失。消息隊列把數據進行持久化直到它們已經被徹底處理,經過這一方式規避了數據丟失風險。許多消息隊列所採用的」插入-獲取-刪除」範式中,在把一個消息從隊列中刪除以前,須要你的處理系統明確的指出該消息已經被處理完畢,從而確保你的數據被安全的保存直到你使用完畢。
  • 擴展性
    由於消息隊列解耦了你的處理過程,因此增大消息入隊和處理的頻率是很容易的,只要另外增長處理過程便可。不須要改變代碼、不須要調節參數。便於分佈式擴容。
  • 削峯
    在訪問量劇增的狀況下,應用仍然須要繼續發揮做用,可是這樣的突發流量沒法提早預知;若是覺得了能處理這類瞬間峯值訪問爲標準來投入資源隨時待命無疑是巨大的浪費。使用消息隊列可以使關鍵組件頂住突發的訪問壓力,而不會由於突發的超負荷的請求而徹底崩潰。
  • 可恢復性
    系統的一部分組件失效時,不會影響到整個系統。消息隊列下降了進程間的耦合度,因此即便一個處理消息的進程掛掉,加入隊列中的消息仍然能夠在系統恢復後被處理。
  • 順序保證
    在大多使用場景下,數據處理的順序都很重要。大部分消息隊列原本就是排序的,而且能保證數據會按照特定的順序來處理。
  • 緩衝
    在任何重要的系統中,都會有須要不一樣的處理時間的元素。消息隊列經過一個緩衝層來幫助任務最高效率的執行,該緩衝有助於控制和優化數據流通過系統的速度。以調節系統響應時間。
  • 異步通訊
    有些業務不想也不須要當即處理消息。消息隊列提供了異步處理機制,容許用戶把一個消息放入隊列,但並不當即處理它。想向隊列中放入多少消息就放多少,而後在須要的時候再去處理它們。

消息中間件的兩種模式

PTP模式 (點對點)使用Queue做爲通訊載體

P2P模式包含三個角色:消息隊列(Queue),發送者(Sender),接收者(Receiver)。每一個消息都被髮送到一個特定的隊列,接收者從隊列中獲取消息。隊列保留着消息,直到他們被消費或超時。數據庫

P2P的特色:apache

  • 每一個消息只有一個消費者(Consumer)(即一旦被消費,消息就再也不在消息隊列中)
  • 發送者和接收者之間在時間上沒有依賴性,也就是說當發送者發送了消息以後,無論接收者有沒有正在運行它不會影響到消息被髮送到隊列
  • 接收者在成功接收消息以後需向隊列應答成功
  • 若是但願發送的每一個消息都會被成功處理的話,那麼須要P2P模式

Pub/Sub模式 (發佈/訂閱 廣播)使用Topic做爲通訊載體

消息生產者(發佈)將消息發佈到topic中,同時有多個消息消費者(訂閱)消費該消息。和點對點方式不一樣,發佈到topic的消息會被全部訂閱者消費。
queue實現了負載均衡,將producer生產的消息發送到消息隊列中,由多個消費者消費。但一個消息只能被一個消費者接受,當沒有消費者可用時,這個消息會被保存直到有一個可用的消費者。
topic實現了發佈和訂閱,當你發佈一個消息,全部訂閱這個topic的服務都能獲得這個消息,因此從1到N個訂閱者都能獲得一個消息的拷貝瀏覽器

Pub/Sub的特色安全

  • 每一個消息能夠有多個消費者
  • 發佈者和訂閱者之間有時間上的依賴性。針對某個主題(Topic)的訂閱者,它必須建立一個訂閱者以後,才能消費發佈者的消息。
  • 爲了消費消息,訂閱者必須保持運行的狀態。
  • 若是但願發送的消息能夠不被作任何處理、或者只被一個消息者處理、或者能夠被多個消費者處理的話,那麼能夠採用Pub/Sub模型。

消息中間件解決的問題

異步通訊

場景說明:用戶在註冊後,須要發註冊郵件和註冊短信,傳統的作法有兩種:1.串行; 2.並行
1.串行方式:將註冊信息寫入數據庫後,發送註冊郵件,再發送註冊短信,以上三個任務所有完成後才返回給客戶端。 這有一個問題是,郵件,短信並非必須的,它只是一個通知,而這種作法讓客戶端等待沒有必要等待的東西.
2.並行方式:將註冊信息寫入數據庫後,發送郵件的同時,發送短信,以上三個任務完成後,返回給客戶端,並行的方式能提升處理的時間。
假設三個業務節點分別使用50ms,串行方式使用時間150ms,並行使用時間100ms。雖然並性已經提升的處理時間,可是,前面說過,郵件和短信對我正常的使用網站沒有任何影響,客戶端沒有必要等着其發送完成才顯示註冊成功,應該是寫入數據庫後就返回.服務器

3.消息隊列
引入消息隊列後,把發送郵件,短信不是必須的業務邏輯異步處理
在這裏插入圖片描述
由此能夠看出,引入消息隊列後,用戶的響應時間就等於寫入數據庫的時間+寫入消息隊列的時間(能夠忽略不計),引入消息隊列後處理後,響應時間是串行的3倍,是並行的2倍。網絡

應用解耦

這是一個高耦合度系統的例子
在這裏插入圖片描述
先是來一我的找他要求發送數據給一個新的系統H,系統A的同窗要修改代碼而後在那個代碼里加入調用新系統H的流程。

一會那個系統B是個陳舊老系統要下線了,告訴系統A的同窗:別給我發送數據了,接着系統A再次修改代碼再也不給這個系統B。

而後若是要是某個下游系統忽然宕機了呢?

系統A的調用代碼裏是否是會拋異常?那系統A的同窗會收到報警說異常了,結果他還要去care是下游哪一個系統宕機了。

因此在實際的系統架構設計中,若是所有采起這種系統耦合的方式,在某些場景下絕對是不合適的,系統耦合度太嚴重。

而且互相耦合起來並非核心鏈路的調用,而是一些非核心的場景(好比上述的數據消費)致使了系統耦合,這樣會嚴重的影響上下游系統的開發和維護效率。

所以在上述系統架構中,就能夠採用MQ中間件來實現系統解耦。

系統A就把本身的一份核心數據發到MQ裏,下游哪一個系統感興趣本身去消費便可,不須要了就取消數據的消費,以下圖所示:
在這裏插入圖片描述

流量削峯

  • 場景1
    假設你有一個系統,平時正常的時候每秒可能就幾百個請求,每秒幾百請求是能夠輕鬆抗住的,
    可是偶爾在高峯期一會兒來了每秒鐘幾千請求,彈指一揮間出現了流量高峯,爲了抗住這個高峯,可能會選擇擴充機器,增長到10臺,可是高峯事後,每秒就幾百個請求,這不是有點浪費機器資源嗎?
    可是若是你就部署一臺機器,那會致使瞬時高峯時,一會兒壓垮你的系統,由於絕對沒法抗住每秒幾千的請求高峯。
    此時咱們就能夠用MQ中間件來進行流量削峯。全部機器前面部署一層MQ,平時每秒幾百請求你們均可以輕鬆接收消息。
    一旦到了瞬時高峯期,一下涌入每秒幾千的請求,就能夠積壓在MQ裏面,而後那一臺機器慢慢的處理和消費。
    等高峯期過了,再消費一段時間,MQ裏積壓的數據就消費完畢了。
    這個就是很典型的一個MQ的用法,用有限的機器資源承載高併發請求,若是業務場景容許異步削峯,高峯期積壓一些請求在MQ裏,而後高峯期過了,後臺系統在必定時間內消費完畢再也不積壓的話,那就很適合用這種技術方案。
    在這裏插入圖片描述
  • 場景2
    秒殺活動,通常會由於流量過大,致使應用掛掉,爲了解決這個問題,通常在應用前端加入消息隊列。
    做用:
    1.能夠控制活動人數,超過此必定閥值的訂單直接丟棄
    2.能夠緩解短期的高流量壓垮應用(應用程序按本身的最大處理能力獲取訂單)

待補充

消息中間件經常使用協議

  • AMQP協議
    AMQP即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不一樣產品,不一樣開發語言等條件的限制。
    優勢:可靠、通用

  • MQTT協議
    MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通信協議,有可能成爲物聯網的重要組成部分。該協議支持全部平臺,幾乎能夠把全部聯網物品和外部鏈接起來,被用來當作傳感器和致動器(好比經過Twitter讓房屋聯網)的通訊協議。
    優勢:格式簡潔、佔用帶寬小、移動端通訊、PUSH、嵌入式系統

  • STOMP協議
    STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息協議,是一種爲MOM(Message Oriented Middleware,面向消息的中間件)設計的簡單文本協議。STOMP提供一個可互操做的鏈接格式,容許客戶端與任意STOMP消息代理(Broker)進行交互。
    優勢:命令模式(非topic\queue模式)

  • XMPP協議
    XMPP(可擴展消息處理現場協議,Extensible Messaging and Presence Protocol)是基於可擴展標記語言(XML)的協議,多用於即時消息(IM)以及在線現場探測。適用於服務器之間的準即時操做。核心是基於XML流傳輸,這個協議可能最終容許因特網用戶向因特網上的其餘任何人發送即時消息,即便其操做系統和瀏覽器不一樣。
    優勢:通用公開、兼容性強、可擴展、安全性高,但XML編碼格式佔用帶寬大

  • 其餘基於TCP/IP自定義的協議
    有些特殊框架(如:redis、kafka、zeroMq等)根據自身須要未嚴格遵循MQ規範,而是基於TCP\IP自行封裝了一套協議,經過網絡socket接口進行傳輸,實現了MQ的功能。

經常使用中間件介紹

  • RocketMQ
    阿里系下開源的一款分佈式、隊列模型的消息中間件,原名Metaq,3.0版本名稱改成RocketMQ,是阿里參照kafka設計思想使用java實現的一套mq。同時將阿里系內部多款mq產品(Notify、metaq)進行整合,只維護核心功能,去除了全部其餘運行時依賴,保證核心功能最簡化,在此基礎上配合阿里上述其餘開源產品實現不一樣場景下mq的架構,目前主要多用於訂單交易系統。
    具備如下特色:
    可以保證嚴格的消息順序
    提供針對消息的過濾功能
    提供豐富的消息拉取模式
    高效的訂閱者水平擴展能力
    實時的消息訂閱機制
    億級消息堆積能力
    官方提供了一些不一樣於kafka的對比差別:
    https://rocketmq.apache.org/docs/motivation/

  • RabbitMQ
    使用Erlang編寫的一個開源的消息隊列,自己支持不少的協議:AMQP,XMPP, SMTP,STOMP,也正是如此,使的它變的很是重量級,更適合於企業級的開發。同時實現了Broker架構,核心思想是生產者不會將消息直接發送給隊列,消息在發送給客戶端時先在中心隊列排隊。對路由(Routing),負載均衡(Load balance)、數據持久化都有很好的支持。多用於進行企業級的ESB整合。
  • 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等。

  • Redis
    使用C語言開發的一個Key-Value的NoSQL數據庫,開發維護很活躍,雖然它是一個Key-Value數據庫存儲系統,但它自己支持MQ功能,因此徹底能夠當作一個輕量級的隊列服務來使用。對於RabbitMQ和Redis的入隊和出隊操做,各執行100萬次,每10萬次記錄一次執行時間。測試數據分爲128Bytes、512Bytes、1K和10K四個不一樣大小的數據。實驗代表:入隊時,當數據比較小時Redis的性能要高於RabbitMQ,而若是數據大小超過了10K,Redis則慢的沒法忍受;出隊時,不管數據大小,Redis都表現出很是好的性能,而RabbitMQ的出隊性能則遠低於Redis。

  • Kafka
    Apache下的一個子項目,使用scala實現的一個高性能分佈式Publish/Subscribe消息隊列系統,具備如下特性:
    快速持久化:經過磁盤順序讀寫與零拷貝機制,能夠在O(1)的系統開銷下進行消息持久化;
    高吞吐:在一臺普通的服務器上既能夠達到10W/s的吞吐速率;
    高堆積:支持topic下消費者較長時間離線,消息堆積量大;
    徹底的分佈式系統:Broker、Producer、Consumer都原生自動支持分佈式,依賴zookeeper自動實現複雜均衡;
    支持Hadoop數據並行加載:對於像Hadoop的同樣的日誌數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。

  • 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切換開銷。

主要消息中間件的比較

在這裏插入圖片描述

相關文章
相關標籤/搜索