在介紹什么消息中間件之前,先介紹幾個概念:
一、什么是消息
消息是指軟件對象之間進行交互作用和通訊利用的一種方式。

二、什么是中間件
非底層操作系統軟件,非業務應用軟件,不是直接給最終用戶使用的,不能直接給客戶帶來價值的軟件統稱為中間件
三、什么是消息隊列
消息隊列是消息中間件的一種實現方式。

四、什么是消息中間件
關注於數據的發送和接受,利用高效可靠的異步消息傳遞機制進行平台無關的數據交流,並基於數據通信來進行分布式系統的集成。通過提供消息傳遞和消息排隊模型,它可以在分布式環境下擴展進程間的通信。

這可能比較抽象,既然消息隊列是實現消息中間件的一種方式,不如我們從它的實際應用場景中,來進一步理解它,消息隊列的應用場景主要有一下幾個方面:
- 1) 異步處理
場景說明:提供新用戶注冊后,發送短信或郵件的功能
傳統的做法有有兩種 1.串行方式;2.並行方式
2、串行方式:將注冊信息寫入數據庫成功后,發送注冊郵件,再發送注冊短信。以上三個任務全部完成后,返回給客戶端。

2、並行方式:將注冊信息寫入數據庫成功后,發送注冊郵件的同時,發送注冊短信。以上三個任務完成后,返回給客戶端。與串行的差別是,並行的方式可以提高處理的時間

假設三個業務節點每個使用50毫秒鍾,不考慮網絡等其他開銷,則串行方式的時間是150毫秒,並行的時間可能是100毫秒。
因為CPU在單位時間內處理的請求數是一定的,假設CPU1秒內吞吐量是100次。則串行方式1秒內CPU可處理的請求量是7次(1000/150)。並行方式處理的請求量是10次(1000/100)
小結:如以上案例描述,傳統的方式系統的性能(並發量,吞吐量,響應時間)會有瓶頸。
引入消息隊列,將不是必須的業務邏輯,異步處理。改造后的架構如下:

按照以上約定,用戶的響應時間相當於是注冊信息寫入數據庫的時間,也就是50毫秒。注冊郵件,發送短信寫入消息隊列后,直接返回,因此寫入消息隊列的速度很快,基本可以忽略,因此用戶的響應時間可能是50毫秒。因此架構改變后,系統的吞吐量提高到每秒20 QPS。比串行提高了3倍,比並行提高了兩倍。
- 2) 應用解耦
場景說明:用戶下單后,訂單系統需要通知庫存系統。傳統的做法是,訂單系統調用庫存系統的接口。

傳統模式的缺點:假如庫存系統無法訪問,則訂單減庫存將失敗,從而導致訂單失敗,訂單系統與庫存系統耦合
引入應用消息隊列后的方案:

訂單系統:用戶下單后,訂單系統完成持久化處理,將消息寫入消息隊列,返回用戶訂單下單成功
庫存系統:訂閱下單的消息,采用拉/推的方式,獲取下單信息,庫存系統根據下單信息,進行庫存操作
假如:在下單時庫存系統不能正常使用。也不影響正常下單,因為下單后,訂單系統寫入消息隊列就不再關心其他的后續操作了。實現訂單系統與庫存系統的應用解耦
- 3) 流量削峰
場景說明:秒殺活動,一般會因為流量過大,導致流量暴增,應用掛掉。為解決這個問題,一般需要在應用前端加入消息隊列。通過加入消息隊列完成如下功能:
a、可以控制活動的人數
b、可以緩解短時間內高流量壓垮應用

用戶的請求,服務器接收后,首先寫入消息隊列。假如消息隊列長度超過最大數量,則直接拋棄用戶請求或跳轉到錯誤頁面。秒殺業務根據消息隊列中的請求信息,再做后續處理
五、消息中間件常用協議
- 1) AMQP協議(Advanced Message Queuing Protocol)
AMQP是一個提供統一消息服務的應用層標准高級消息隊列協議,是應用層協議的一個開放標准,為面向消息的中間件設計。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不同產品,不同開發語言等條件的限制。
優點:可靠、通用
- 2) MQTT協議(Message Queuing Telemetry Transport,消息隊列遙測傳輸)
MQTT是IBM開發的一個即時通訊協議,有可能成為物聯網的重要組成部分。該協議支持所有平台,幾乎可以把所有聯網物品和外部連接起來,被用來當做傳感器和致動器(比如通過Twitter讓房屋聯網)的通信協議。
優點:格式簡潔、占用帶寬小、移動端通信、PUSH、嵌入式系統
- 3) STOMP協議(Streaming Text Orientated Message Protocol)
STOMP是流文本定向消息協議,是一種為MOM(Message Oriented Middleware,面向消息的中間件)設計的簡單文本協議。STOMP提供一個可互操作的連接格式,允許客戶端與任意STOMP消息代理(Broker)進行交互。
優點:命令模式(非topic\queue模式)
- 4) XMPP協議(Extensible Messaging and Presence Protocol,可擴展消息處理現場協議)
XMPP是基於可擴展標記語言(XML)的協議,多用於即時消息(IM)以及在線現場探測。適用於服務器之間的准即時操作。核心是基於XML流傳輸,這個協議可能最終允許因特網用戶向因特網上的其他任何人發送即時消息,即使其操作系統和瀏覽器不同。
優點:通用公開、兼容性強、可擴展、安全性高,但XML編碼格式占用帶寬大
- 5) 其他基於TCP/IP自定義的協議
有些特殊框架(如:redis、kafka、zeroMq等)根據自身需要未嚴格遵循MQ規范,而是基於TCP\IP自行封裝了一套協議,通過網絡socket接口進行傳輸,實現了MQ的功能。
補充:Java消息服務 即JMS,是一個Java平台中關於面向消息中間的API,用於在兩個應用程序之間或者分布式系統中發送消息,進行異步通信。
JMS與AMQP的區別
a、JMS是定義了統一的接口,來對消息操作進行統一;AMQP是通過規定協議來統一數據交互的格式
b、JMS限定了必須使用Java語言;AMQP只是協議,不規定實現方式,因此是跨語言的。
c、JMS規定了兩種消息模型 點對點、發布訂閱;而AMQP的消息模型有7種
六、常見的消息中間件(MQ)
- 1) RocketMQ
阿里系下開源的一款分布式、隊列模型的消息中間件,原名Metaq,3.0版本名稱改為RocketMQ,是阿里參照kafka設計思想使用java實現的一套mq。同時將阿里系內部多款mq產品(Notify、metaq)進行整合,只維護核心功能,去除了所有其他運行時依賴,保證核心功能最簡化,在此基礎上配合阿里上述其他開源產品實現不同場景下mq的架構,目前主要多用於訂單交易系統。
特點:能夠保證嚴格的消息順序、提供針對消息的過濾功能、提供豐富的消息拉取模式、高效的訂閱者水平擴展能力、實時的消息訂閱機制、億級消息堆積能力
- 2) RabbitMQ
使用Erlang編寫的一個開源的消息隊列,本身支持很多的協議:AMQP,XMPP, SMTP,STOMP,也正是如此,使的它變的非常重量級,更適合於企業級的開發。同時實現了Broker架構,核心思想是生產者不會將消息直接發送給隊列,消息在發送給客戶端時先在中心隊列排隊。對路由(Routing),負載均衡(Load balance)、數據持久化都有很好的支持。多用於進行企業級的ESB整合。
- 3) ActiveMQ
使用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等。
- 4) Redis
使用C語言開發的一個Key-Value的NoSQL數據庫,雖然它是一個Key-Value數據庫存儲系統,但它本身支持MQ功能,所以完全可以當做一個輕量級的隊列服務來使用。
補充:Redis與RabbitMQ的比較:
入隊:數據大小<10K時,Redis的性能要高於RabbitMQ,數據大於10K時,RabbitMQ更勝一籌
出隊:無論數據大小,Redis都表現出非常好的性能,而RabbitMQ的出隊性能則遠低於Redis。
- 5) Kafka
使用scala實現的一個高性能分布式Publish/Subscribe消息隊列系統,具有以下特性:
a、快速持久化:通過磁盤順序讀寫與零拷貝機制,可以在O(1)的系統開銷下進行消息持久化;
b、高吞吐:在一台普通的服務器上既可以達到10W/s的吞吐速率;
c、高堆積:支持topic下消費者較長時間離線,消息堆積量大;
d、完全的分布式系統:Broker、Producer、Consumer都原生自動支持分布式,依賴zookeeper自動實現復雜均衡;
e、支持Hadoop數據並行加載:對於像Hadoop的一樣的日志數據和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。
- 6) ZeroMQ
號稱最快的消息隊列系統,專門為高吞吐量/低延遲的場景開發,在金融界的應用中經常使用,偏重於實時數據通信場景。ZMQ能夠實現RabbitMQ不擅長的高級/復雜的隊列,但是開發人員需要自己組合多種技術框架,開發成本高。因此ZeroMQ具有一個獨特的非中間件的模式,更像一個socket library,你不需要安裝和運行一個消息服務器或中間件,因為你的應用程序本身就是使用ZeroMQ API完成邏輯服務的角色。但是ZeroMQ僅提供非持久性的隊列,如果down機,數據將會丟失。如:Twitter的Storm中使用ZeroMQ作為數據流的傳輸。ZeroMQ套接字是與傳輸層無關的:ZeroMQ套接字對所有傳輸層協議定義了統一的API接口。默認支持 進程內(inproc) ,進程間(IPC) ,多播,TCP協議,在不同的協議之間切換只要簡單的改變連接字符串的前綴。可以在任何時候以最小的代價從進程間的本地通信切換到分布式下的TCP通信。ZeroMQ在背后處理連接建立,斷開和重連邏輯。特性:
a、無鎖的隊列模型:對於跨線程間的交互(用戶端和session)之間的數據交換通道pipe,采用無鎖的隊列算法CAS;在pipe的兩端注冊有異步事件,在讀或者寫消息到pipe的時,會自動觸發讀寫事件。
b、批量處理的算法:對於批量的消息,進行了適應性的優化,可以批量的接收和發送消息。
c、多核下的線程綁定,無須CPU切換:區別於傳統的多線程並發模式,信號量或者臨界區,zeroMQ充分利用多核的優勢,每個核綁定運行一個工作者線程,避免多線程之間的CPU切換開銷。
