MQ 系列 2:消息中間件的技術選型

1 背景

在高併發、高消息吞吐的互聯網場景中,我們經常會使用消息隊列(Message Queue)作爲基礎設施,在服務端架構中擔當消息中轉、消息削峯、事務異步處理 等職能。

對於那些不需要實時響應的的業務,我們都可以放在消息隊列中進行傳輸。下面是用戶在進行系統註冊的時候場景,充分體現 MQ 的作用

可以看到用戶註冊的過程步驟 1 + 步驟 2,從請求到響應總共耗時 55 ms。消息消費 + 短信發送的時間比較長,從上面看花了 5s 多,一般讓消息隊列服務去處理,用戶靜靜等待短信送達即可。

消息隊列中間件(簡稱消息中間件)是指利用高效可靠的消息傳遞機制進行與平臺無關的數據交流,並基於數據通信來進行分佈式系統的集成。通過提供消息傳遞和消息排隊模型,它可以在分佈式環境下提供應用解耦、

彈性伸縮、冗餘存儲、流量削峯、異步通信、數據同步等等功能,其作爲分佈式系統架構中的一個重要組件,有着舉足輕重的地位。

2 消息中間件的組成

Broker:消息服務器,以服務的形式運行在 server 端,給各個業務系統提供核心消息數據的中轉服務。

Producer:消息生產者,業務的發起方,負責生產消息傳輸給 broker。

Consumer:消息消費者,業務的處理方,負責從 broker 獲取消息並進行業務邏輯處理

Topic:主題模塊,發佈 / 訂閱模式下的消息統一彙集地,不同生產者向 topic 發送消息,由 MQ 服務器分發到不同的訂閱者,實現消息的廣播

Queue:隊列,PTP 模式下,特定生產者向特定 queue 發送消息,消費者訂閱特定的 queue 完成指定消息的接收。

Message:消息體,根據不同通信協議定義的固定格式進行編碼的數據包,來封裝業務數據,實現消息的傳輸。

這邊以 kafka 爲例子,這是典型的集羣模式,Kafka 通過 Zookeeper 管理集羣配置,選舉 leader,以及在 Consumer Group 發生變化時進行 rebalance。Producer 使用 push 模式將消息發佈到 broker,Consumer 使用 pull 模式從 broker 訂閱並消費消息。

3 消息中間件的模式分類 

PTP 點對點:使用 queue 作爲通信載體 

消息生產者生產消息發送到 queue 中,然後消息消費者從 queue 中取出並且消費消息。 

不可重複消費,消息被消費以後,queue 中不再存儲,所以消息消費者不可能消費到已經被消費的消息。Queue 支持存在多個消費者,但是對一個消息而言,只會有一個消費者可以消費。

Pub/Sub 發佈訂閱(廣播):使用 topic 作爲通信載體 

消息生產者(發佈)將消息發佈到 topic 中,同時有多個消息消費者(訂閱)消費該消息。和點對點方式不同,發佈到 topic 的消息會被所有訂閱者消費,所以從 1 到 N 個訂閱者都能得到這個消息的拷貝。

4 消息中間件的優勢

系統解耦:交互系統之間沒有直接的調用關係,只是通過消息傳輸,故系統侵入性不強,耦合度低。

削峯、提高系統響應時間:例如原來的一套邏輯,可將緊急重要(需要立刻響應)的業務放到該調用方法中,響應要求不高的使用消息隊列,放到 MQ 隊列中,供消費者處理。

業務的有序性處理:先來先處理,比如一個系統處理某件事需要很長一段時間,但是在處理這件事情時候,有其他人也發出了請求,可以把請求放在消息隊裏,一個一個來處理

爲大數據處理架構提供服務:通過消息作爲整合,大數據的背景下,消息隊列還與實時處理架構整合,爲數據處理提供性能支持。 

5 消息中間件常用協議

AMQP 協議、MQTT 協議、STOMP 協議、XMPP 協議、其他基於 TCP/IP 自定義的協議。

6 豐富的消息中間件開源市場

目前開源的消息中間還是很豐富的,大家用的比較多的比如 ActiveMQ、RabbitMQ、Kafka、RocketMQ、ZeroMQ 等。

但是每個人的業務場景不一樣,受限於系統的規模,業務的取捨(如延遲容忍度,死信、重試的需求,可持久化需求),並不是每一款消息中間件都能滿足你的需求。

除了個別大廠會進行自研(如 阿里的 Rocket MQ、滴滴的 DD MQ)之外,大部分同學還是要對選型有一些思考的。各自都有各自的側重點,選擇合適自己、揚長避短無疑是最好的方式。

6.1 主流 MQ 介紹

下面基於受衆程度,對三款主流的 MQ 做介紹,通過各項指標上的對比,給出我們在實際應用場景中的建議。

RabbitMQ:

採用 Erlang 語言實現的 AMQP 協議的消息中間件,起源於金融系統,廣泛應用在分佈式系統中,承擔消息轉發的職責。RabbitMQ 發展歷史比較久遠,影響範圍比較大,被很多開發者認可,在可靠性、可用性、可擴展性、功能性方面有着非凡表現。

RocketMQ:

阿里開源的消息中間件,目前已經捐獻給 Apache 基金會,它是由 Java 語言開發的,具備高吞吐量、高可用性、適合大規模分佈式系統應用等特點。並且在阿里的雙 11、618 等重要活動中經受住了考驗。

Kafka:

起初是由 LinkedIn 公司採用 Scala 語言開發的一個分佈式、多分區、多副本且基於 zookeeper 協調的分佈式消息系統,現已捐獻給 Apache 基金會。它是一種高吞吐量的分佈式發佈訂閱消息系統,以可水平擴展和高吞吐率而被廣泛使用。

目前越來越多的開源分佈式處理系統如 Cloudera、Apache Storm、Spark、Flink 等都支持與 Kafka 集成。

6.2 主流 MQ 對比

vDRPih

6.3 選型建議

6.3.1 系統建設規模角度

中小型系統建議選用 RabbitMQ,數據量相對較小,選型應首選功能比較完備的,所以 kafka 排除。RocketMQ 是阿里出品,如果阿里放棄維護,中小型公司一般很難投入人力進行 RocketMQ 的定製化開發,因此不推薦。

6.3.2 業務規模角度

根據具體使用規模在 RocketMQ 和 kafka 之間二選一。

大型業務系統:有實際的業務體量需求,比如足夠大規模的分佈式環境,以及足夠大的數據量。這時候 RocketMQ  和 kafka 都是 10w + 的吞吐量,都可以在考慮範圍內。

如果你有業務定製需求,可以優先選用 RocketMQ,畢竟是開源的,大的業務系統也願意花精力去優化 JAVA 源碼的。至於 kafka,根據業務方向選擇,類似日誌採集功能,首選 kafka,因爲他在日誌上報、監控數據採集方面有着大規模的實踐經驗,這也是他們主打的應用場景。

具體該選哪個,看使用場景。引入 MQ 之後,也會有一定的弊端,必然一定程度上降低系統可用性,增加複雜性。

6.3.3 功能性層面選型

n8Uv1Z

6.3.4 性能層面

功能維度是消息中間件選型中的一個重要的參考維度,但性能也是考慮的一個重要環節。

吞吐量角度:Kafka 在開啓冪等、事務功能的時候會使其性能降低,RabbitMQ 在開啓 rabbitmq_tracing 插件的時候也會極大地影響其性能。消息中間件的性能一般是指其吞吐量,雖然從功能維度上來說,RabbitMQ 的優勢要大於 Kafka,但是 Kafka 的吞吐量要比 RabbitMQ 高出 1 至 2 個數量級,一般 RabbitMQ 的單機 QPS 在萬級別之內,而 Kafka 的單機 QPS 可以維持在十萬級別,甚至可以達到百萬級。

時延角度:另外一個是時延,作爲性能維度的一個重要指標,卻往往在消息中間件領域所被忽視,因爲一般使用消息中間件的場景對時效性的要求並不是很高,如果要求時效性完全可以採用 RPC 的方式實現。消息中間件具備消息堆積的能力。

Kafka 是 ms 以內,RabbitMQ 是 us 級別的。 

6.3.5 高可用角度

高可用角度是指系統的出錯概率和無故障運行時長。

如消息丟失,是使用消息中間件時所不得不面對的一個共同點,其背後消息可靠性也是衡量消息中間件好壞的一個關鍵因素。尤其是在金融支付領域,消息可靠性尤爲重要。然而說到可靠性必然要說到可用性,注意這兩者之間的區別,消息中間件的可靠性是指對消息不丟失的保障程度;、

而消息中間件的可用性是指無故障運行的時間百分比,通常用幾個 9 來衡量。

對應的 RabbitMQ 是通過鏡像環形隊列實現多副本及強一致性語義的。多副本可以保證在 master 節點宕機異常之後可以提升 slave 作爲新的 master 而繼續提供服務來保障可用性。

Kafka 設計之初是爲日誌處理而生,給人們留下了數據可靠性要求不高的不良印象,但是隨着版本的升級優化,其可靠性得到極大的增強,詳細可以參考 KIP101。

目前情況,在金融支付領域使用 RabbitMQ 居多,而在日誌處理、大數據等方面 Kafka 使用居多。 

6.3.6 運維管理層面

消息中間件一個很重要的考慮層面是運維管理,比如:申請、審覈、監控、告警、管理、容災、部署等。

對消息中間件的使用  從使用、接入規範、全方位的監控、流量統計和分析等方面,提供有效的基準數據,也可以在檢測到異常的情況配合告警,以便運維、開發人員的迅速介入。除了一般的監控項(比如硬件、GC 等)之外,對於消息中間件還需要關注端到端時延、消息審計、消息堆積等方面。

對於 RabbitMQ 而言,最正統的監控管理工具莫過於 rabbitmq_management 插件了,但是社區內還有 AppDynamics, Collectd, DataDog, Ganglia, Munin, Nagios, New Relic, Prometheus, Zenoss 等多種優秀的產品。

Kafka 在此方面也毫不遜色,比如:Kafka Manager, Kafka Monitor, Kafka Offset Monitor, Burrow, Chaperone, Confluent Control Center 等產品,尤其是 Cruise 還可以提供自動化運維的功能。

機房故障就要涉及異地容災了,關鍵點在於如何有效的進行數據複製,對於 Kafka 而言,可以參考 MirrorMarker、uReplicator 等產品,而 RabbitMQ 可以參考 Federation 和 Shovel。 

6.3.7 社區力度及生態發展

Kafka 和 RabbitMQ 都有一系列開源的監控管理產品,這些都得益於其社區及生態的迅猛發展。Rocket MQ 基於阿里的推廣,整個生態也是不錯的。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/4PSgVlO5s0ViKfpsWMusag