1、什麼是消息中間件
2、消息中間件組成
3、消息隊列的的傳輸模式
4、消息中間件的優點
5、消息中間件應用場景
6、消息中間件經常使用協議
7、常見消息中間件介紹與比較
8、參考文章html
消息隊列已經逐漸成爲企業IT系統內部通訊的核心手段。它具備低耦合、可靠投遞、廣播、流量控制、最終一致性等一系列功能,成爲異步RPC的主要手段之一。當今市面上有不少主流的消息中間件,如老牌的ActiveMQ、RabbitMQ,煊赫一時的Kafka,阿里巴巴自主開發RocketMQ等。前端
消息服務器,爲server提供消息核心服務git
消息生產者,業務的發起方,負責生產消息傳輸給brokerredis
消息消費者,業務的處理方,負責從broker獲取消息並進行業務邏輯處理數據庫
主題,發佈訂閱模式下的消息統一聚集地,不一樣生產者向topic發送消息,由MQ服務器分發到不一樣的訂閱者,實現消息的廣播編程
隊列,PTP模式下,特定生產者向特定queue發送消息,消費者訂閱特定的queue完成指定消息的接收瀏覽器
消息體,根據不一樣通訊協議定義的固定格式進行編碼的數據包,來封裝業務數據,實現消息的傳輸安全
點對點模型 用於 消息生產者 和 消息消費者 之間 點到點 的通訊。消息生產者將消息發送到由某個名字標識的特定消費者。這個名字實際上對於消費服務中的一個 隊列(Queue),在消息傳遞給消費者以前它被 存儲 在這個隊列中。隊列消息 能夠放在 內存 中也能夠 持久化,以保證在消息服務出現故障時仍然可以傳遞消息。服務器
傳統的點對點消息中間件一般由 消息隊列服務、消息傳遞服務、消息隊列 和 消息應用程序接口 API 組成,其典型的結構以下圖所示。網絡
特色
每一個消息只用一個消費者;
發送者和接受者沒有時間依賴;
接受者確認消息接受和處理成功。
示意圖以下所示
發佈者/訂閱者 模型支持向一個特定的 消息主題 生產消息。0 或 多個訂閱者 可能對接收來自 特定消息主題 的消息感興趣。
在這種模型下,發佈者和訂閱者彼此不知道對方,就比如是匿名公告板。這種模式被概況爲:多個消費者能夠得到消息,在 發佈者 和 訂閱者 之間存在 時間依賴性。發佈者須要創建一個 訂閱(subscription),以便可以消費者訂閱。訂閱者 必須保持 持續的活動狀態 並 接收消息。
在這種狀況下,在訂閱者 未鏈接時,發佈的消息將在訂閱者 從新鏈接 時 從新發布,以下圖所示:
特性
每一個消息能夠有多個訂閱者;
客戶端只有訂閱後才能接收到消息;
持久訂閱和非持久訂閱。
注意
發佈者和訂閱者有時間依賴:接受者和發佈者只有創建訂閱關係才能收到消息;
持久訂閱:訂閱關係創建後,消息就不會消失,無論訂閱者是否都在線;
非持久訂閱:訂閱者爲了接受消息,必須一直在線。當只有一個訂閱者時約等於點對點模式
交互系統之間沒有直接的調用關係,只是經過消息傳輸,故系統侵入性不強,耦合度低。
例如原來的一套邏輯,完成支付可能涉及先修改訂單狀態、計算會員積分、通知物流配送幾個邏輯才能完成;經過MQ架構設計,就可將緊急重要(須要馬上響應)的業務放到該調用方法中,響應要求不高的使用消息隊列,放到MQ隊列中,供消費者處理。
經過消息做爲整合,大數據的背景下,消息隊列還與實時處理架構整合,爲數據處理提供性能支持。
Java消息服務(Java Message Service,JMS)應用程序接口是一個Java平臺中關於面向消息中間件(MOM)的API,用於在兩個應用程序之間,或分佈式系統中發送消息,進行異步通訊。
JMS中的P2P和Pub/Sub消息模式:點對點(point to point, queue)與發佈訂閱(publish/subscribe,topic)最初是由JMS定義的。這兩種模式主要區別或解決的問題就是發送到隊列的消息可否重複消費(多訂閱)。
當你須要使用 消息隊列 時,首先須要考慮它的必要性。可使用消息隊列的場景有不少,最經常使用的幾種,是作 應用程序鬆耦合、異步處理模式、發佈與訂閱、最終一致性、錯峯流控 和 日誌緩衝 等。反之,若是須要 強一致性,關注業務邏輯的處理結果,則使用 RPC 顯得更爲合適。
1.1 介紹
有些業務不想也不須要當即處理消息。消息隊列提供了異步處理機制,容許用戶把一個消息放入隊列,但並不當即處理它。想向隊列中放入多少消息就放多少,而後在須要的時候再去處理它們。
1.2 具體場景
用戶爲了使用某個應用,進行註冊,系統須要發送註冊郵件並驗證短信。對這兩個操做的處理方式有兩種:串行及並行。
(1)串行方式:新註冊信息生成後,先發送註冊郵件,再發送驗證短信;
在這種方式下,須要最終發送驗證短信後再返回給客戶端。
(2)並行處理:新註冊信息寫入後,由發短信和發郵件並行處理;
在這種方式下,發短信和發郵件 需處理完成後再返回給客戶端。
假設以上三個子系統處理的時間均爲50ms,且不考慮網絡延遲,則總的處理時間:
串行:50+50+50=150ms 並行:50+50 = 100ms
若使用消息隊列:
並在寫入消息隊列後當即返回成功給客戶端,則總的響應時間依賴於寫入消息隊列的時間,而寫入消息隊列的時間自己是能夠很快的,基本能夠忽略不計,所以總的處理時間相比串行提升了2倍,相比並行提升了一倍;
2.1 介紹
交互系統之間沒有直接的調用關係,只是經過消息傳輸,故系統侵入性不強,耦合度低。
2.2 具體場景
用戶使用QQ相冊上傳一張圖片,人臉識別系統會對該圖片進行人臉識別,通常的作法是,服務器接收到圖片後,圖片上傳系統當即調用人臉識別系統,調用完成後再返回成功,以下圖所示:
該方法有以下缺點:
(1)人臉識別系統被調失敗,致使圖片上傳失敗;
(2)延遲高,須要人臉識別系統處理完成後,再返回給客戶端,即便用戶並不須要當即知道結果;
(3)圖片上傳系統與人臉識別系統之間互相調用,須要作耦合;
若使用消息隊列:
客戶端上傳圖片後,圖片上傳系統將圖片信息如uin、批次寫入消息隊列,直接返回成功;而人臉識別系統則定時從消息隊列中取數據,完成對新增圖片的識別。
此時圖片上傳系統並不須要關心人臉識別系統是否對這些圖片信息的處理、以及什麼時候對這些圖片信息進行處理。事實上,因爲用戶並不須要當即知道人臉識別結果,人臉識別系統能夠選擇不一樣的調度策略,按照閒時、忙時、正常時間,對隊列中的圖片信息進行處理。
3.1 介紹
當上下游系統 處理能力存在差距的時候,利用 消息隊列 作一個通用的 「漏斗」,進行 限流控制。在下游有能力處理的時候,再進行分發。
3.2 具體場景
用戶在支付系統成功結帳後,訂單系統會經過短信系統向用戶推送扣費通知。短信系統 可能因爲 短板效應,速度卡在 網關 上(每秒幾百次請求),跟 前端的併發量 不是一個數量級。因而,就形成 支付系統 和 短信系統 的處理能力出現差別化。
然而用戶晚上個半分鐘左右收到短信,通常是不會有太大問題的。若是沒有消息隊列,兩個系統之間經過 協商、滑動窗口 等複雜的方案也不是說不能實現。但 系統複雜性 指數級增加,勢必在 上游 或者 下游 作 存儲,而且要處理 定時、擁塞 等一系列問題。並且每當有 處理能力有差距 的時候,都須要 單獨 開發一套邏輯來維護這套邏輯。
因此,利用中間系統轉儲兩個系統的通訊內容,並在下游系統有能力處理這些消息的時候,再處理這些消息,是一套相對較通用的方式。
應用案例
(1)把消息隊列當成可靠的 消息暫存地,進行必定程度的 消息堆積;
(2)定時進行消息投遞,好比模擬 用戶秒殺 訪問,進行 系統性能壓測。
具體場景
用戶新上傳了一批照片, 人臉識別系統須要對這個用戶的全部照片進行聚類,聚類完成後由對帳系統從新生成用戶的人臉索引(加快查詢)。這三個子系統間由消息隊列鏈接起來,前一個階段的處理結果放入隊列中,後一個階段從隊列中獲取消息繼續處理。
該方法有以下優勢:
(1)避免了直接調用下一個系統致使當前系統失敗;
(2)每一個子系統對於消息的處理方式能夠更爲靈活,能夠選擇收到消息時就處理,能夠選擇定時處理,也能夠劃分時間段按不一樣處理速度處理;
將消息隊列用在 日誌處理 中,好比 Kafka
的應用,解決 海量日誌 傳輸和緩衝的問題。
應用案例
把日誌進行集中收集,用於計算 PV
、用戶行爲分析 等等。
在大多使用場景下,數據處理的順序都很重要。大部分消息隊列原本就是排序的,而且能保證數據會按照特定的順序來處理。
消息隊列通常都內置了 高效的通訊機制,所以也能夠用於單純的 消息通信,好比實現 點對點消息隊列 或者 聊天室 等。
AMQP即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不一樣產品,不一樣開發語言等條件的限制。
優勢:可靠、通用
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通信協議,有可能成爲物聯網的重要組成部分。該協議支持全部平臺,幾乎能夠把全部聯網物品和外部鏈接起來,被用來當作傳感器和致動器(好比經過Twitter讓房屋聯網)的通訊協議。
優勢:格式簡潔、佔用帶寬小、移動端通訊、PUSH、嵌入式系統
STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息協議,是一種爲MOM(Message Oriented Middleware,面向消息的中間件)設計的簡單文本協議。STOMP提供一個可互操做的鏈接格式,容許客戶端與任意STOMP消息代理(Broker)進行交互。
優勢:命令模式(非topic\queue模式)
XMPP(可擴展消息處理現場協議,Extensible Messaging and Presence Protocol)是基於可擴展標記語言(XML)的協議,多用於即時消息(IM)以及在線現場探測。適用於服務器之間的準即時操做。核心是基於XML流傳輸,這個協議可能最終容許因特網用戶向因特網上的其餘任何人發送即時消息,即便其操做系統和瀏覽器不一樣。
優勢:通用公開、兼容性強、可擴展、安全性高,但XML編碼格式佔用帶寬大
有些特殊框架(如:redis、kafka、zeroMq等)根據自身須要未嚴格遵循MQ規範,而是基於TCP\IP自行封裝了一套協議,經過網絡socket接口進行傳輸,實現了MQ的功能。
1.1 ActiveMQ
簡介
ActiveMQ 是由 Apache 出品,ActiveMQ 是一個徹底支持JMS1.1 和 J2EE 1.4 規範的 JMS Provider 實現。它很是快速,支持 多種語言的客戶端 和 協議,並且能夠很是容易的嵌入到企業的應用環境中,並有許多高級功能。
主要特性
(1)服從JMS規範:JMS 規範提供了良好的標準和保證,包括:同步 或 異步 的消息分發,一次和僅一次的消息分發,消息接收 和 訂閱 等等。聽從 JMS 規範的好處在於,不論使用什麼 JMS 實現提供者,這些基礎特性都是可用的;
(2)鏈接靈活性:ActiveMQ 提供了普遍的 鏈接協議,支持的協議有:HTTP/S,IP 多播,SSL,TCP,UDP 等等。對衆多協議的支持讓 ActiveMQ 擁有了很好的靈活性;
(3)支持的協議種類多:OpenWire、STOMP、REST、XMPP、AMQP;
(4)持久化插件和安全插件:ActiveMQ 提供了 多種持久化 選擇。並且,ActiveMQ 的安全性也能夠徹底依據用戶需求進行 自定義鑑權 和 受權;
(5)支持的客戶端語言種類多:除了 Java 以外,還有:C/C++,.NET,Perl,PHP,Python,Ruby;
(6)代理集羣:多個 ActiveMQ 代理 能夠組成一個 集羣 來提供服務;
(7)異常簡單的管理:ActiveMQ 是以開發者思惟被設計的。因此,它並不須要專門的管理員,由於它提供了簡單又使用的管理特性。有不少中方法能夠 監控 ActiveMQ 不一樣層面的數據,包括使用在 JConsole 或者在 ActiveMQ 的 Web Console 中使用 JMX。經過處理 JMX 的告警消息,經過使用 命令行腳本,甚至能夠經過監控各類類型的 日誌。
部署環境
ActiveMQ 能夠運行在 Java 語言所支持的平臺之上。使用 ActiveMQ 須要:
(1)Java JDK
(2)ActiveMQ 安裝包
優勢
(1)跨平臺 (JAVA 編寫與平臺無關,ActiveMQ 幾乎能夠運行在任何的 JVM 上);
(2)能夠用 JDBC:能夠將 數據持久化 到數據庫。雖然使用 JDBC 會下降 ActiveMQ 的性能,可是數據庫一直都是開發人員最熟悉的存儲介質;
(3)支持 JMS 規範:支持 JMS 規範提供的 統一接口;
(4)支持 自動重連 和 錯誤重試機制;
(5)有安全機制:支持基於 shiro,jaas 等多種 安全配置機制,能夠對 Queue/Topic 進行 認證和受權;
(6)監控完善:擁有完善的 監控,包括 Web Console,JMX,Shell 命令行,Jolokia 的 RESTful API;
9)7界面友善:提供的 Web Console 能夠知足大部分狀況,還有不少 第三方的組件 可使用,好比 hawtio;
缺點
(1)社區活躍度不及 RabbitMQ 高;
(2)根據其餘用戶反饋,會出莫名其妙的問題,會 丟失消息;
(3)目前重心放到 activemq 6.0 產品 Apollo,對 5.x 的維護較少;
(4)不適合用於 上千個隊列 的應用場景;
1.2 RabbitMQ
RabbitMQ 於 2007 年發佈,是一個在 AMQP (高級消息隊列協議)基礎上完成的,可複用的企業消息系統,是當前最主流的消息中間件之一。
主要特性
(1)可靠性:提供了多種技術可讓你在 性能 和 可靠性 之間進行 權衡。這些技術包括 持久性機制、投遞確認、發佈者證明 和 高可用性機制;
(2)靈活的路由:消息在到達隊列前是經過 交換機 進行 路由 的。RabbitMQ 爲典型的路由邏輯提供了 多種內置交換機 類型。若是你有更復雜的路由需求,能夠將這些交換機組合起來使用,你甚至能夠實現本身的交換機類型,而且當作 RabbitMQ 的 插件 來使用;
(3)消息集羣:在相同局域網中的多個 RabbitMQ 服務器能夠 聚合 在一塊兒,做爲一個獨立的邏輯代理來使用;
(4)隊列高可用:隊列能夠在集羣中的機器上 進行鏡像,以確保在硬件問題下還保證 消息安全;
(5)支持多種協議:支持 多種消息隊列協議;
(6)支持多種語言:用 Erlang 語言編寫,支持只要是你能想到的 全部編程語言;
(7)管理界面: RabbitMQ 有一個易用的 用戶界面,使得用戶能夠 監控 和 管理 消息 Broker 的許多方面;
(8)跟蹤機制:若是 消息異常,RabbitMQ 提供消息跟蹤機制,使用者能夠找出發生了什麼;
(9)插件機制:提供了許多 插件,來從多方面進行擴展,也能夠編寫本身的插件。
部署環境
RabbitMQ 能夠運行在 Erlang 語言所支持的平臺之上,包括 Solaris,BSD,Linux,MacOSX,TRU64,Windows 等。使用 RabbitMQ 須要:
(1)ErLang 語言包
(2)RabbitMQ 安裝包
優勢
(1)因爲 Erlang 語言的特性,消息隊列性能較好,支持 高併發;
(2)健壯、穩定、易用、跨平臺、支持 多種語言、文檔齊全;
(3)有消息 確認機制 和 持久化機制,可靠性高;
(4)高度可定製的 路由;
(5)管理界面 較豐富,在互聯網公司也有較大規模的應用,社區活躍度高。
缺點
(1)儘管結合 Erlang 語言自己的併發優點,性能較好,可是不利於作 二次開發和維護;
(2)實現了 代理架構,意味着消息在發送到客戶端以前能夠在 中央節點 上排隊。此特性使得 RabbitMQ 易於使用和部署,可是使得其 運行速度較慢,由於中央節點 增長了延遲,消息封裝後 也比較大;
(3)須要學習 比較複雜 的 接口和協議,學習和維護成本較高。
1.3 RocketMQ
簡介
RocketMQ 出自 阿里 的開源產品,用 Java 語言實現,在設計時參考了 Kafka,並作出了本身的一些改進,消息可靠性上 比 Kafka 更好。RocketMQ 在阿里內部被普遍應用在 訂單,交易,充值,流計算,消息推送,日誌流式處理,binglog 分發 等場景。
主要特性
(1)基於 隊列模型:具備 高性能、高可靠、高實時、分佈式 等特色;
(2)Producer、Consumer、隊列 都支持 分佈式;
(3)Producer 向一些隊列輪流發送消息,隊列集合 稱爲 Topic。Consumer 若是作 廣播消費,則一個 Consumer 實例消費這個 Topic 對應的 全部隊列;若是作 集羣消費,則 多個 Consumer 實例 平均消費 這個 Topic 對應的隊列集合;
(4)可以保證 嚴格的消息順序;
(5)提供豐富的 消息拉取模式;
(6)高效的訂閱者 水平擴展能力;
(7)實時 的 消息訂閱機制;
(8)億級 消息堆積 能力;
(9)較少的外部依賴。
部署環境
RocketMQ 能夠運行在 Java 語言所支持的平臺之上。使用 RocketMQ 須要:
(1)Java JDK
(2)安裝 git、Maven
(3)RocketMQ 安裝包
優勢
(1)單機 支持 1 萬以上 持久化隊列;
(2)RocketMQ 的全部消息都是 持久化的,先寫入系統 PAGECACHE,而後 刷盤,能夠保證 內存 與 磁盤 都有一份數據,而 訪問 時,直接 從內存讀取。
(3)模型簡單,接口易用(JMS 的接口不少場合並不太實用);
(4)性能很是好,能夠容許 大量堆積消息 在 Broker 中;
(5)支持 多種消費模式,包括 集羣消費、廣播消費等;
(6)各個環節 分佈式擴展設計,支持 主從 和 高可用;
(7)開發度較活躍,版本更新很快。
缺點
(1)支持的 客戶端語言 很少,目前是 Java 及 C++,其中 C++ 還不成熟;
(2)RocketMQ 社區關注度及成熟度也不及前二者;
(3)沒有 Web 管理界面,提供了一個 CLI (命令行界面) 管理工具帶來 查詢、管理 和 診斷各類問題;
(4)沒有在 MQ 核內心實現 JMS 等接口;
1.4 Kafka
簡介
Apache Kafka 是一個 分佈式消息發佈訂閱 系統。它最初由 LinkedIn 公司基於獨特的設計實現爲一個 分佈式的日誌提交系統 (a distributed commit log),以後成爲 Apache 項目的一部分。Kafka 性能高效、可擴展良好 而且 可持久化。它的 分區特性,可複製 和 可容錯 都是其不錯的特性。
主要特性
(1)快速持久化:能夠在 O(1) 的系統開銷下進行 消息持久化;
(2)高吞吐:在一臺普通的服務器上既能夠達到 10W/s 的 吞吐速率;
(3)徹底的分佈式系統:Broker、Producer 和 Consumer 都原生自動支持 分佈式,自動實現 負載均衡;
(4)支持 同步 和 異步 複製兩種 高可用機制;
(5)支持 數據批量發送 和 拉取;
(6)零拷貝技術(zero-copy):減小 IO 操做步驟,提升 系統吞吐量;
(7)數據遷移、擴容 對用戶透明;
(8)無需停機 便可擴展機器;
(9)其餘特性:豐富的 消息拉取模型、高效 訂閱者水平擴展、實時的 消息訂閱、億級的 消息堆積能力、按期刪除機制;
部署環境
使用 Kafka 須要:
(1)Java JDK
(2)Kafka 安裝包
優勢
(1)客戶端語言豐富:支持 Java、.Net、PHP、Ruby、Python、Go 等多種語言;
(2)高性能:單機寫入 TPS 約在 100 萬條/秒,消息大小 10 個字節;
(3)提供 徹底分佈式架構,並有 replica 機制,擁有較高的 可用性 和 可靠性,理論上支持 消息無限堆積;
(4)支持批量操做;
(5)消費者 採用 Pull 方式獲取消息。消息有序,經過控制 可以保證全部消息被消費且僅被消費 一次;
(6)有優秀的第三方 Kafka Web 管理界面 Kafka-Manager;
(7)在日誌領域 比較成熟,被多家公司和多個開源項目使用。
缺點
(1)Kafka 單機超過 64 個 隊列/分區 時,Load 時會發生明顯的飆高現象。隊列 越多,負載 越高,發送消息 響應時間變長;
(2)使用 短輪詢方式,實時性 取決於 輪詢間隔時間;
(3)消費失敗 不支持重試;
(4)支持 消息順序,可是 一臺代理宕機 後,就會產生 消息亂序;
(5)社區更新較慢。
2.1 比較一
ZeroMq 最好,RabbitMq 次之, ActiveMq 最差。這個結論來自於如下這篇文章。
http://blog.x-aeon.com/2013/04/10/a-quick-message-queue-benchmark-activemq-rabbitmq-hornetq-qpid-apollo/
測試環境:
Model: Dell Studio 1749
CPU: Intel Core i3 @ 2.40 GH
RAM: 4 Gb
OS: Windows 7 64 bits
其中包括持久化消息和瞬時消息的測試。注意這篇文章裏面提到的MQ,都是採用默認配置的,並沒有調優。
更多的統計圖請參看我提供的文章url。
2.2 比較二
ZeroMq 最好,RabbitMq次之, ActiveMq最差。這個結論來自於一下這篇文章。http://www.cnblogs.com/amityat/archive/2011/08/31/2160293.html
顯示的是發送和接受的每秒鐘的消息數。整個過程共產生1百萬條1K的消息。測試的執行是在一個Windows Vista上進行的。
2.3 持久化消息比較
zeroMq不支持,activeMq和rabbitMq都支持。持久化消息主要是指:MQ down或者MQ所在的服務器down了,消息不會丟失的機制。
2.4 技術點:可靠性、靈活的路由、集羣、事務、高可用的隊列、消息排序、問題追蹤、可視化管理工具、插件系統、社區
RabbitMq最好,ActiveMq次之,ZeroMq最差。固然ZeroMq也能夠作到,不過本身必須手動寫代碼實現,代碼量不小。尤爲是可靠性中的:持久性、投遞確認、發佈者證明和高可用性。因此在可靠性和可用性上,RabbitMQ是首選,雖然ActiveMQ也具有,可是它性能不及RabbitMQ。
2.5 高併發
從實現語言來看,RabbitMQ最高,緣由是它的實現語言是天生具有高併發高可用的erlang語言。
2.6 整體比較
結論:
(1)Kafka 在於 分佈式架構,RabbitMQ 基於 AMQP 協議 來實現,RocketMQ 的思路來源於 Kafka,改爲了 主從結構,在 事務性 和 可靠性 方面作了優化。普遍來講,電商、金融 等對 事務一致性 要求很高的,能夠考慮 RabbitMQ 和 RocketMQ,對 性能要求高 的可考慮 Kafka。
(2)按照目前網絡上的資料,RabbitMQ、activeMQ、zeroMQ三者中,綜合來看,RabbitMQ是首選,可是activeMQ與Java結合度比較好。