1. 程式人生 > >訊息中介軟體選型

訊息中介軟體選型

目前開源的訊息中介軟體可謂是琳琅滿目,能讓大家耳熟能詳的就有很多,比如ActiveMQ、RabbitMQ、Kafka、RocketMQ、ZeroMQ等。

一:各類訊息佇列簡述:

1、ActiveMQ是Apache出品的、採用Java語言編寫的完全基於JMS1.1規範的面向訊息的中介軟體,為應用程式提供高效的、可擴充套件的、穩定的和安全的企業級訊息通訊。不過由於歷史原因包袱太重,目前市場份額沒有後面三種訊息中介軟體多。

2、RabbitMQ是採用Erlang語言實現的AMQP協議的訊息中介軟體,最初起源於金融系統,用於在分散式系統中儲存轉發訊息。RabbitMQ發展到今天,被越來越多的人認可,這和它在可靠性、可用性、擴充套件性、功能豐富等方面的卓越表現是分不開的。

3、Kafka起初是由LinkedIn公司採用Scala語言開發的一個分散式、多分割槽、多副本且基於zookeeper協調的分散式訊息系統,現已捐獻給Apache基金會。它是一種高吞吐量的分散式釋出訂閱訊息系統,以可水平擴充套件和高吞吐率而被廣泛使用。目前越來越多的開源分散式處理系統如Cloudera、Apache Storm、Spark、Flink等都支援與Kafka整合。

4、RocketMQ是阿里開源的訊息中介軟體,目前已經捐獻個Apache基金會,它是由Java語言開發的,具備高吞吐量、高可用性、適合大規模分散式系統應用等特點,經歷過雙11的洗禮,實力不容小覷。

目前市面上的訊息中介軟體還有很多,比如騰訊系的PhxQueue、CMQ、CKafka,又比如基於Go語言的NSQ,有時人們也把類似Redis的產品也看做訊息中介軟體的一種,當然它們都很優秀。

二:訊息選型要點概述

1、功能維度

(1)、優先順序佇列

優先順序佇列不同於先進先出佇列,優先順序高的訊息具備優先被消費的特權,這樣可以為下游提供不同訊息級別的保證。不過這個優先順序也是需要有一個前提的:如果消費者的消費速度大於生產者的速度,並且訊息中介軟體伺服器(一般簡單的稱之為Broker)中沒有訊息堆積,那麼對於傳送的訊息設定優先順序也就沒有什麼實質性的意義了,因為生產者剛傳送完一條訊息就被消費者消費了,那麼就相當於Broker中至多隻有一條訊息,對於單條訊息來說優先順序是沒有什麼意義的。

(2)、延遲佇列

當你在網上購物的時候是否會遇到這樣的提示:“三十分鐘之內未付款,訂單自動取消”?這個是延遲佇列的一種典型應用場景。延遲佇列儲存的是對應的延遲訊息,所謂“延遲訊息”是指當訊息被髮送以後,並不想讓消費者立刻拿到訊息,而是等待特定時間後,消費者才能拿到這個訊息進行消費。延遲佇列一般分為兩種:基於訊息的延遲和基於佇列的延遲。基於訊息的延遲是指為每條訊息設定不同的延遲時間,那麼每當佇列中有新訊息進入的時候就會重新根據延遲時間排序,當然這也會對效能造成極大的影響。實際應用中大多采用基於佇列的延遲,設定不同延遲級別的佇列,比如5s、10s、30s、1min、5mins、10mins等,每個佇列中訊息的延遲時間都是相同的,這樣免去了延遲排序所要承受的效能之苦,通過一定的掃描策略(比如定時)即可投遞超時的訊息。

(3)、重試佇列

重試佇列其實可以看成是一種回退佇列,具體指消費端消費訊息失敗時,為防止訊息無故丟失而重新將訊息回滾到Broker中。與回退佇列不同的是重試佇列一般分成多個重試等級,每個重試等級一般也會設定重新投遞延時,重試次數越多投遞延時就越大。舉個例子:訊息第一次消費失敗入重試佇列Q1,Q1的重新投遞延遲為5s,在5s過後重新投遞該訊息;如果訊息再次消費失敗則入重試佇列Q2,Q2的重新投遞延遲為10s,在10s過後再次投遞該訊息。以此類推,重試越多次重新投遞的時間就越久。

(4)、消費模式

消費模式分為推(push)模式和拉(pull)模式。推模式是指由Broker主動推送訊息至消費端,實時性較好,不過需要一定的流制機制來確保服務端推送過來的訊息不會壓垮消費端。而拉模式是指消費端主動向Broker端請求拉取(一般是定時或者定量)訊息,實時性較推模式差,但是可以根據自身的處理能力而控制拉取的訊息量。

(5)、廣播消費

訊息一般有兩種傳遞模式:點對點(P2P,Point-to-Point)模式和釋出/訂閱(Pub/Sub)模式。對於點對點的模式而言,訊息被消費以後,佇列中不會再儲存,所以訊息消費者不可能消費到已經被消費的訊息。雖然佇列可以支援多個消費者,但是一條訊息只會被一個消費者消費。釋出訂閱模式定義瞭如何向一個內容節點發布和訂閱訊息,這個內容節點稱為主題(topic),主題可以認為是訊息傳遞的中介,訊息釋出者將訊息釋出到某個主題,而訊息訂閱者則從主題中訂閱訊息。主題使得訊息的訂閱者與訊息的釋出者互相保持獨立,不需要進行接觸即可保證訊息的傳遞,釋出/訂閱模式在訊息的一對多廣播時採用。RabbitMQ是一種典型的點對點模式,而Kafka是一種典型的釋出訂閱模式。但是RabbitMQ中可以通過設定交換器型別來實現釋出訂閱模式而達到廣播消費的效果,Kafka中也能以點對點的形式消費。

(6)、訊息回溯

一般訊息在消費完成之後就被處理了,之後再也不能消費到該條訊息。訊息回溯正好相反,是指訊息在消費完成之後,還能消費到之前被消費掉的訊息。對於訊息而言,經常面臨的問題是“訊息丟失”,至於是真正由於訊息中介軟體的缺陷丟失還是由於使用方的誤用而丟失一般很難追查,如果訊息中介軟體本身具備訊息回溯功能的話,可以通過回溯消費復現“丟失的”訊息進而查出問題的源頭之所在。

(7)、訊息堆積+持久化

流量削峰是訊息中介軟體的一個非常重要的功能,而這個功能其實得益於其訊息堆積能力。從某種意義上來講,如果一個訊息中介軟體不具備訊息堆積的能力,那麼就不能把它看做是一個合格的訊息中介軟體。訊息堆積分記憶體式堆積和磁碟式堆積。RabbitMQ是典型的記憶體式堆積,但這並非絕對,在某些條件觸發後會有換頁動作來將記憶體中的訊息換頁到磁碟(換頁動作會影響吞吐),或者直接使用惰性佇列來將訊息直接持久化至磁碟中。Kafka是一種典型的磁碟式堆積,所有的訊息都儲存在磁碟中。一般來說,磁碟的容量會比記憶體的容量要大得多,對於磁碟式的堆積其堆積能力就是整個磁碟的大小。從另外一個角度講,訊息堆積也為訊息中介軟體提供了冗餘儲存的功能。

(8)、訊息過濾

訊息過濾是指按照既定的過濾規則為下游使用者提供指定類別的訊息。就以kafka而言,完全可以將不同類別的訊息傳送至不同的topic中,由此可以實現某種意義的訊息過濾,或者Kafka還可以根據分割槽對同一個topic中的訊息進行分類。不過更加嚴格意義上的訊息過濾應該是對既定的訊息採取一定的方式按照一定的過濾規則進行過濾。同樣以Kafka為例,可以通過客戶端提供的ConsumerInterceptor介面或者Kafka Stream的filter功能進行訊息過濾。

(9)、多協議支援

訊息是資訊的載體,為了讓生產者和消費者都能理解所承載的資訊(生產者需要知道如何構造訊息,消費者需要知道如何解析訊息),它們就需要按照一種統一的格式描述訊息,這種統一的格式稱之為訊息協議。有效的訊息一定具有某種格式,而沒有格式的訊息是沒有意義的。一般訊息層面的協議有AMQP、MQTT、STOMP、XMPP等,支援的協議越多其應用範圍就會越廣,通用性越強。

(10)、跨語言支援

對很多公司而言,其技術棧體系中會有多種程式語言,如C/C++、JAVA、Go、PHP等,訊息中介軟體本身具備應用解耦的特性,如果能夠進一步的支援多客戶端語言,那麼就可以將此特性的效能擴大。跨語言的支援力度也可以從側面反映出一個訊息中介軟體的流行程度。

(11)、流量控制

流量控制針對的是傳送方和接收方速度不匹配的問題,提供一種速度匹配服務抑制傳送速率使接收方應用程式的讀取速率與之相適應。

(12)、安全機制

在Kafka 0.9版本之後就開始增加了身份認證和許可權控制兩種安全機制。身份認證是指客戶端與服務端連線進行身份認證,包括客戶端與Broker之間、Broker與Broker之間、Broker與ZooKeeper之間的連線認證,目前支援SSL、SASL等認證機制。許可權控制是指對客戶端的讀寫操作進行許可權控制,包括對訊息或Kafka叢集操作許可權控制。許可權控制是可插拔的,並支援與外部的授權服務進行整合。對於RabbitMQ而言,其同樣提供身份認證(TLS/SSL、SASL)和許可權控制(讀寫操作)的安全機制。

下表是對Kafka與RabbitMQ功能的總結性對比及補充說明。

2、效能維度

訊息中介軟體的效能一般是指其吞吐量,雖然從功能維度上來說,RabbitMQ的優勢要大於Kafka,但是Kafka的吞吐量要比RabbitMQ高出1至2個數量級,一般RabbitMQ的單機QPS在萬級別之內,而Kafka的單機QPS可以維持在十萬級別,甚至可以達到百萬級。

時延作為效能維度的一個重要指標,卻往往在訊息中介軟體領域所被忽視,因為一般使用訊息中介軟體的場景對時效性的要求並不是很高,如果要求時效性完全可以採用RPC的方式實現。訊息中介軟體具備訊息堆積的能力,訊息堆積越大也就意味著端到端的時延也就越長,與此同時延時佇列也是某些訊息中介軟體的一大特色。那麼為什麼還要關注訊息中介軟體的時延問題呢?訊息中介軟體能夠解耦系統,對於一個時延較低的訊息中介軟體而言,它可以讓上游生產者傳送訊息之後可以迅速的返回,也可以讓消費者更加快速的獲取到訊息,在沒有堆積的情況下可以讓整體上下游的應用之間的級聯動作更加高效,雖然不建議在時效性很高的場景下使用訊息中介軟體,但是如果所使用的訊息中介軟體的時延方面比較優秀,那麼對於整體系統的效能將會是一個不小的提升。

3、可靠性+可用性

訊息丟失是使用訊息中介軟體時所不得不面對的一個同點,其背後訊息可靠性也是衡量訊息中介軟體好壞的一個關鍵因素。尤其是在金融支付領域,訊息可靠性尤為重要。然而說到可靠性必然要說到可用性,注意這兩者之間的區別,訊息中介軟體的可靠性是指對訊息不丟失的保障程度;而訊息中介軟體的可用性是指無故障執行的時間百分比,通常用幾個9來衡量。

4、社群力度+生態發展

對於目前流行的程式語言而言,如Java、Python,如果你在使用過程中遇到了一些異常,基本上可以通過搜尋引擎的幫助來得到解決,因為一個產品用的人越多,踩過的坑也就越多,對應的解決方案也就越多。對於訊息中介軟體也同樣適用,如果你選擇了一種“生僻”的訊息中介軟體,可能在某些方面運用的得心應手,但是版本更新緩慢、遇到棘手問題也難以得到社群的支援而越陷越深;相反如果你選擇了一種“流行”的訊息中介軟體,其更新力度大,不僅可以迅速的彌補之前的不足,而且也能順應技術的快速發展來變更一些新的功能,這樣可以讓你以“站在巨人的肩膀上”。