Apache RocketMQ背後的設計思路與最佳實踐

摘要:爲了更好地讓開發者們更加深入瞭解阿里開源,阿里云云棲社區在3月1號了舉辦“阿里開源項目最佳實踐”在線技術峯會,直播講述了當前阿里新興和經典開源項目實戰經驗以及背後的開發思路。在本次在線技術峯會上,阿里巴巴中間件架構師馮嘉深入淺出的爲大家講述Apache RocketMQ背後的設計思路、典型場景、最佳實踐以及社區運營與商業化之路。

演講嘉賓介紹:

馮嘉(花名鼬神),阿里巴巴中間件架構師,具有豐富的分佈式軟件架構、高併發網站設計、性能調優經驗,擁有多項分佈式、推薦領域的專利。開源愛好者,關注分佈式、雲計算、大數據領域。目前主要負責阿里巴巴消息中間件生態輸出、MQ商業化 ,Apache RocketMQ 聯合創始人,社區佈道者,目前主要負責Apache RocketMQ的雲端商業化版本Aliware MQ。

本次的分享主要圍繞了以下四個議題:
一、分佈式消息領域的相關產品以及技術體系
二、Apache RocketMQ的發展歷史、架構設計以及Aliware MQ能夠提供的高級特性
三、Apache RocketMQ作爲消息引擎的典型應用場景、最佳實踐和RocketMQ服務端調優的經驗
四、對於Apache RocketMQ 4.X消息引擎的未來展望以及RocektMQ開源社區演進歷史和發展規劃

一、分佈式消息領域的相關產品以及技術體系

TB1Vhj8PVXXXXbYXpXXXXXXXXXXuploading.4e448015.gif轉存失敗重新上傳取消

下圖所示的是分佈式系統相關的技術領域。

作爲一款消息中間件,RocketMQ需要解決的技術問題其實在分佈式系統領域中都有所體現。

首先如果將分佈式系統的領域按照分佈式通信、分佈式存儲、分佈式計算以及分佈式管理這四大部分進行劃分,其實就會發現在這四大技術棧下有很多的子技術。這裏列舉幾個簡單的例子,比如在分佈式通信領域下對於網絡協議的選擇上面,像RocketMQ是基於TCP的,而基於RocketMQ內核的Aliware MQ是有基於HTTP協議的網關,同時也提供了MQTT協議網關。除了像網絡協議的選擇之外,還會有I/O的模型,這也屬於分佈式通信領域一個非常經典的問題。

通常情況下會將I/O模型分成四種,第一種是所謂的Boss與Worker模型;還有一種是Only Boss模型,所謂的Select線程和事件真正處理的線程都統一在Boss裏面,這樣就減少了線程切換時產生的上下文開銷;第三種I/O模型就是將第一種與第二種I/O模型進行了整合,並利用了統計學原理,在某些比如像內存負載比較重的場景下,從模型一切換到模型二,也就成了所謂的Dynamic Model。第四種I/O模型其實並不常見,它在開源領域有一個與Netty齊名的傳輸層框架Grizzly中會使用到,叫做Leader/Fellow框架,Leader/Fellow其實是將Select線程這部分的選擇權交給了Worker,而在Selector線程裏處理IO事件。聊完了分佈式計算領域再來談一談分佈式存儲領域,這其實也是分佈式領域最複雜,最難攻克的領域,包括結構化存儲、半結構化、非結構化存儲等。除此之外,在分佈式計算領域,主要會涉及Streaming計算、圖計算等相關的內容。而在分佈式管理方面,也會涉及到很多子技術,包括分佈式數據管理,這裏面會牽扯到數據多副本的問題,還有分佈式一致性、協調等,這些都屬於分佈式管理相關領域。

大家對比前後兩幅圖就會發現,在消息領域需要解決的技術棧中的很多問題與分佈式系統中的問題是存在交集的,所以可以說分佈式消息領域融合了很多現代分佈式系統技術中極具挑戰性的研究領域。

那麼目前在業界有哪些比較知名的消息引擎呢?如下圖所示,這裏面幾乎完全列舉了當下比較知名的消息引擎,包括ZeroMQ、推特的Distributedlog、Apache旗下的老牌消息引擎ActiveMQ、AMQP的默認實現RabbitMQ、Kafka、Apache的ActiveMQ下的子項目Artemis、同樣爲Apache的ActiveMQ的子項目的號稱下一代消息引擎的Apollo、商業化的消息引擎IronMQ以及實現了JMS(Java Message Service)標準的OpenMQ,還有就是毫無疑問的今天分享的主角——Apache RocketMQ。

二、Apache RocketMQ的發展歷史、架構設計以及Aliware MQ能夠提供的高級特性

在簡單地爲大家分享了分佈式系統以及分佈式消息系統所使用到的一些技術之後,接着爲大家分享一下RocketMQ的發展歷史、架構設計以及Aliware MQ能夠提供的高級特性。

RocketMQ的發展歷史

下圖展現的就是阿里巴巴消息引擎的發展歷史。在2007年的時候,淘寶實施了“五彩石”項目,“五彩石”用於將交易系統從單機變成分佈式,也是在這個過程中產生了阿里巴巴第一代消息引擎——Notify。在2010年的時候,阿里巴巴B2B部門基於ActiveMQ的5.1版本也開發了自己的一款消息引擎,稱爲Napoli,這款消息引擎在B2B裏面廣泛地被使用,不僅僅是在交易領域,在很多的後臺異步解耦等方面也得到了廣泛的應用。在2011年的時候,業界出現了現在被很多大數據領域所推崇的Kafka消息引擎,阿里巴巴在研究了Kafka的整體機制和架構設計之後,基於Kafka的設計使用Java進行了完全重寫並推出了MetaQ 1.0版本,主要是用於解決順序消息和海量堆積的問題。而在2012年,阿里巴巴對於MetaQ進行了架構重組升級,開發出了MetaQ 2.0,這時就發現MetaQ原本基於Kafka的架構在阿里巴巴如此龐大的體系下很難進行水平擴展,所以在2012年的時候就開發了RocketMQ 3.0版本。很多人會問到RocketMQ 3.0和MetaQ 3.0的區別,其實這兩者是等價的版本,只不過阿里內部使用的稱爲MetaQ 3.0,外部開源稱之爲RocketMQ 3.0。在2015年,又基於RocketMQ開發了阿里雲上的Aliware MQ和Notify 3.0。在2016年的時候,阿里巴巴將RocketMQ的內核引擎捐贈給了Apache基金會。

以上就是RocketMQ的整體發展歷史,其實在阿里巴巴內部圍繞着RocketMQ內核打造了三款產品,分別是MetaQ、Notify和Aliware MQ。這三者分別採用了不同的模型,MetaQ主要使用了拉模型,解決了順序消息和海量堆積問題;Notify主要使用了推模型,解決了事務消息;而云產品Aliware MQ則是提供了商業化的版本。

下圖是RocketMQ在歷年雙11的整體情況,可以看出,從2012年開始,每年RocketMQ在整個雙11當天的消息流轉都會有極大的提升。在2012年大約是100億的消息流轉,在2013年就接近了332億的消息流轉,2014年和2015年都增長得非常迅速,到2015年已經接近6500億消息流轉,在2016年的雙11當天整個阿里巴巴集團線上通過RocketMQ的消息流轉達則到了1.4萬億。

在爲大家介紹完阿里巴巴內部的消息流轉的體量之後,再給大家近距離圍觀一下目前Apache RocketMQ的情況,如下圖所示就是RocketMQ的官網,歡迎大家Star和Fork。

下圖展示的是RocketMQ商業化的雲上版本Aliware MQ的官方入口。

TB1tsZcPVXXXXXsXpXXXXXXXXXXuploading.4e448015.gif轉存失敗重新上傳取消

RocketMQ的整體架構設計

下圖爲大家清晰地展示了RocketMQ的幾個組件,分別是nameserver、broker、producer和consumer。nameserver主要負責對於源數據的管理,包括了對於Topic和路由信息的管理,broker在啓動的時候會去向nameserver註冊並且定時發送心跳,producer在啓動的時候會到nameserver上去拉取Topic所屬的broker具體地址,然後向具體的broker發送消息。

下圖是RocketMQ的消息領域模型,主要分爲Message、Topic、Queue、Offset以及Group這幾部分。

下圖爲RocketMQ服務端的整體架構設計。首先最上層是授權和認證部分,因爲RocketMQ是基於TCP的自行研發的一套線路層協議,所以它需要編解碼以及序列化。再接下來可這一層是健康檢查,在健康檢查之後是流控和熔斷措施,因爲再好的系統也需要流量保護,RocketMQ也是一樣,爲了良好的可用性,RocketMQ提供了針對於不同維度的流量控制。再往下就是存儲,總體而言RocketMQ服務端對於部署運維是非常友好的,目前阿里巴巴內部也有很多系統在進行Docker容器化。

下面這幅圖展示的是SDK的架構圖。毋庸置疑第一步需要做的事情是服務發現,需要去找到發消息或者收消息具體的broker以及broker上的Topic,在此之外SDK還會需要做的事情就是長連接的保活。接下來與服務端相同,要有流量控制以及熔斷機制,另外爲了保證實現高可用性,就需要提供補償機制,這種補償機制表現在發送端的Retry和接收端的Redelivery,也就是重投和重發。接下來,在SDK層還存在元信息通知更新消息,比如nameserver上數據變更就需要進行通知。

下面這幅圖爲大家展示了現在的阿里巴巴內部消息引擎的部署架構圖。從圖中可以看到所謂的kernel就是RocketMQ,在kernel之外還外置了像專門爲物聯網提供解決方案的MQTT網關、主要解決多語言跨網絡問題的HTTP網關、兼容Kafka 0.10.X協議與官方持續保持兼容的Kafka網關。

接下來爲大家分享在Aliware MQ上幾個比較優秀的特性。第一個就是常見的事務消息,這裏的事務消息指的其實是數據發送者事務消息,簡單而言就是在真正地做業務邏輯之前會發送一條半消息到服務端,接下來發送者會執行本地的事務,在完成本地事務之後,如果成功就會向服務端發送一條確認信息,這時候服務端會將之前的半消息事務狀態進行變更;如果失敗了,服務端就會不斷地回調客戶端,來保證發送端的事務一致性。

第二個特性就是我們去年最新研發的一套基於原有多機房部署的集羣模式,利用分佈式鎖和通知機制,藉助Controller組件,設計並實現了高可用架構。請注意,HA Controller是消息引擎高可用架構中降低系統故障恢復時間的一個重要的無狀態組件,通過監聽服務狀態變更,控制狀態機狀態切換,進而完成主從狀態的一系列切換。

Aliware MQ的第三個特性也是非常有意思的,這個特性主要解決的是分佈式鏈路追蹤問題。從下圖中可以非常清楚地看到,消息被髮送到服務端,再投遞給消費者,其中還包括了失敗的次數以及一些時間點的信息。

接下來這個高級特性也是目前在Aliware MQ上公測的所謂的中繼產品,這個產品目前也是在消息引擎中進行孵化的,它主要解決了跨網絡的問題。下圖中左邊是一個VPC私有網絡,右邊其實也是一個私有網絡,如果要讓這兩個私有網絡之間的應用進行網絡互通,就需要爲其搭建一套Relaying中繼集羣,在兩個私有網絡都能夠訪問公網的前提下,通過中繼服務就可以實現兩個私有網絡的雙向通訊。這個特性可以說是極其變態的。想想看,都已經私有網絡了,還有通訊的需求,除了傳統那種複雜的硬件白名單各種配置機制外,中繼服務提供了一種靈活的軟件服務級別的細粒度控制。

三、Apache RocketMQ作爲消息引擎的典型應用場景、最佳實踐和RocketMQ服務端調優的經驗

在第三部分會爲大家分享RocketMQ作爲消息引擎的典型應用場景以及最佳實踐和對於RocketMQ服務端調優的經驗。這部分的分享大致分成五個小部分:

  1. 異構系統的整合,這個問題比較容易理解,在原阿里SOA ESB比較火的年代,很多異構系統需要進行互聯互通。
  2. 應用和應用之間的鬆耦合,這個在阿里巴巴內部很多的同步鏈路到異步鏈路裏面,使用的非常多。
  3. 事件驅動機制和複雜事件架構模型裏面的Backbone,底層的機制可以通過MQ來玩轉。
  4. 數據複製通道,這個有很多比較典型的應用場景,比如模擬MySQL的binlog解析,將數據的變更封裝爲消息,進而複製到遠端的另外一個數據源。
  5. 與流計算引擎的整合,像和Apache Storm、Spark、Flink等框架進行整合,很好的服務於大數據通道。

接下來分享一下RocketMQ的最佳實踐,考慮到官方已經有比較細緻的描述,這裏我會分享一些設計層面的最佳經驗,對實戰也很有幫助。從發送端和接收端來看有如下圖所示的幾個比較重要的部分。

首先對於發送端而言,需要重點關注是三個部分,一個就是發送失敗了怎麼辦,這裏就是send backoff也就是所謂的一種補償。那麼發送失敗了,怎樣進行補償呢?比如現在的機制是三次補償,需要設置每次間隔多少秒,這是就一種很好的補償機制。還有就是send reliability,也就是發送的可靠性。第三塊就是send oneway,也就是在一些大數據場景下不需要響應的情況下,可以採用send oneway的方式來迅速地提高吞吐量。

而對於消費者端而言,有幾塊也需要重點關注。一個是重複消費問題,一般情況下推薦大家通過存儲介質探重。而如果消費失敗了或者消費速度太慢怎麼辦,有什麼樣的方式可以解決呢?一種方案就是通過併發去解決,可以通過提高併發的通道實現。第三塊就是consume batch的問題,在RocketMQ裏面默認的batch是32,如果大家覺得自己消息引擎吞吐量比較低就可以提高batch,但是如果不對於服務端的限制進行調整,batch最多也就只能達到32。

接下來分享一下阿里巴巴內部對於RocketMQ服務端性能調優的幾點經驗總結。

這幾點經驗其實都與I/O相關,首先如果要進行I/O操作,那麼就無法避免文件句柄的調優,這個是達到一個高吞吐必備的系統調優。其次CPU的親和特性,包括線程親和CPU,內存親和CPU,網卡親和CPU,這裏面非常有學問。第三部分就是如何突破內存鎖的限制,無鎖設計是我們所推崇的。第四部分就是NUMA架構Disable問題。這裏簡單提一下NUMA架構,它主要是爲了解決CPU訪問內存的響應性能問題。因爲由於所有CPU都是通過一個內存控制器來讀取內存,隨着CPU核不斷髮展,其響應時間上的性能問題越來越明顯。於是,NUMA架構出現了。NUMA會爲每個CPU核綁定一部分內存,每次在CPU中運行的線程會優先地去訪問該CPU所對應的內存,而當內存不足的時候,會優先把CPU相對應的內存釋放掉。NUM這種默認的內存分配算法對於存儲類產品而言是存在問題的,所以建議大家對於這一部分進行Disable,當然業界也有很多其他的解決方案,比如打開NUMA中的交叉分配方案。
而通過很多的線上觀察,我們發現在線程處理來自外部的請求的時候,對於內存的訪問其實都是隨機的,所以交叉分配方案可以使得線程對於內存的訪問進行打散,具有一定程度上的提升。還有一部分就是PageCache flush調優,因爲MQ的存儲其實是一個文件系統,那麼就避免不了與PageCache打交道,而PageCache裏面就有很多可以進行調優的,包括髒頁回寫,換頁機制等,這些都是進行調優的重點。最後一部分就是對於磁盤的I/O調度的調優,大家都知道在磁盤的I/O調度方面,Linux操作系統默認爲我們提供了四種方式,而通過線上的觀察以及實驗建議大家將默認的調度方式變爲Deadline方式,也就是最後期限調度算法,這樣就可以有效地避免I/O寫請求餓死情況的出現。

四、對於Apache RocketMQ 4.X消息引擎的未來展望以及RocektMQ開源社區演進歷史和發展規劃

接下來爲大家分享最後一部分,就是對於RocketMQ 4.X消息引擎的未來展望。

其實目前我們也在RocketMQ 社區裏面發起了這樣的一個討論,確定了在未來RocketMQ 4.X版本將會專注於電子商務、金融、物聯網以及大數據等領域。而在電子商務領域,RocketMQ重點需要解決的還是高併發的問題;在金融領域重點需要解決的是消息的高可靠,也就是之前提到的分佈式事務處理;在物聯網loT領域需要重點解決的一個問題就是所謂的海量終端在線也就是海量長連接問題;而在大數據領域,RocketMQ需要重點攻克的就是海量的消息吞吐問題。

有了以上的目標之後,我們希望能夠基於統一的架構進行實現,那麼這其實很容易想到就是基於某種規範去實現四個領域裏面的編程API的統一。下圖中列舉出了五個業界非常有名的消息領域的規範。CORBA是分佈式領域裏面一個非常古老的規範,CORBA裏面有專門針對消息的一章就是Notification Service,CORBA的協議是非常學術化的。而JMS是大家都比較熟悉的,它是Java領域的一套編程API。MQTT和AMQP都是OASIS組織下的協議,MQTT是面向物聯網的線路層協議,而AMQP也是消息領域的一個線路層協議,很明顯,它只是一個協議。ActiveMQ中內置了OpenWire,它也是一個線路層協議。上述的這些協議在我們看來都無法完全滿足對於四個領域的需求標準。

下圖列出了目前在Apache官網上發起的關於Open Messaging規範的討論,大家可以到官網上進行仔細閱讀。目前這套API的初稿已經完成了,我們也在與阿里巴巴之外的像推特和雅虎這些MQ廠商進行聯繫,討論並驗證這套規範能否適用於之前提到的電子商務等四個領域。

這套規範要想健康地成長,成爲真正被大家所認可的規範還需要強大的後盾。那麼這個時候,Linux基金會和Apache基金會就會毫無疑問地走入我們的視野。RocketMQ目前雖然已經捐贈給了Apache基金會並作爲Apache的一個孵化項目,但是經過我們的深入調研,發現在Apache社區發起這樣的一套規範是不太合適的,這與apache way甚至是相悖的。所以還需要Linux基金會的幫助。其實在Linux基金會中就會有很多開源的規範,我們也希望這套規範能夠在Linux基金會下進行推進。

下圖就是爲大家列出最近RocketMQ 4.0在開源社區發佈後,預期在RocketMQ 4.1至4.3版本中將會提供的一些特性。大家可以到官網上進行查看,感興趣也可以參與進來。

剛纔整體的介紹了RocketMQ產品的大致情況,接下來爲大家介紹一下RocketMQ社區的發展情況。RocketMQ目前主要的開發和貢獻是在中國大陸以及包括韓國和日本在內的亞洲其他國家進行的,而我們希望RocketMQ的社區的開發者和參與者能夠遍佈全球。下圖是在Apache中摘錄的Apache的參與者在全球的分佈情況,未來也希望在全球範圍內都有的開發者能夠非常積極地參與到Apache RocketMQ項目中來。

爲了達成上面提出的目標,我們最近也在思考做這樣的幾件事情:首先會舉辦不定期的Workshop和Meetup,最近發佈RocketMQ 4.0的時候就在國內以線下的方式舉辦了編程馬拉松,並且收穫了比較不錯的效果,也發現了一些願意持續跟進社區的參與者。

聊完了社區之後,還想與大家分享一下在RocketMQ的孵化過程中我們對於Apache基金會的初步認識。下圖中的幾個關鍵字其實非常準確地描述了Apache Way,那麼什麼是Apache Way呢?Apache非常強調對於軟件進行合作開發,並且在實際上對於商業化的協議也是比較友好的,Apache還強調產品需要保證高質量,講究尊重和誠實,並且強調基於技術的交互和對於規範的堅定實現的信念,最後還是將產品的安全特性作爲強制要求進行考慮。

下圖就是在Apache基金會對於項目進行孵化的流程。RocketMQ在孵化期間也是按照這個流程一路走來的。接下來就爲大家簡單介紹一下,首先要進行孵化需要選好自己的領路人,也就是Champion的概念,領路人將會對於項目在Apache上的孵化起到非常大的推進作用,所以如果大家有志於將自己的產品推到Apache上,一個好的領路人對於項目能夠進入Apache是非常重要的。這裏面的具體流程就是在社區起草一個提議,當提議通過了之後可以召集大家討論一下提議的可行性,然後進行投票,在投票之後如果社區願意接受產品的話就會真正地開啓自己的Apache孵化之旅,也就是達到了圖中最後一步的Podling。

下圖中列舉了目前RocketMQ在Apache社區的活躍度,其實從郵件列表中很容易直觀地看出項目在社區的活躍狀態。目前在Apache社區中最活躍的幾個項目就是Hadoop、Spark以及Flink等,而且Hadoop和Spark的每月郵件列表的數量統計基本在400封到600封之間,目前RocketMQ的郵件列表裏面每月郵件分發次數已經可以接近Hadoop和Spark的數字了,這裏還是要感謝大家參與到RocketMQ的社區裏面。

接下來還要分享一下Apache項目的組織結構。最上面是董事會,每個項目在Apache裏面都有自己的PMC組織,也就是項目管理委員會,在項目管理委員會之下是Committer。而每個項目之間是獨立分開的,如果你屬於這個項目的PMC並不代表還會屬於另外一個項目的PMC。而且在項目之下還會有多個子項目,正如剛纔講到的Apache的ActiveMQ是一個比較老牌的項目,在這個項目之下至少有4個子項目。而RocketMQ目前是一個孵化的項目,如果能夠孵化成功就能夠成爲頂級的項目,也就是下圖中標有PMC字樣的框框。

下圖是Apache社區對於開發者和貢獻者的表彰。首先在開始時只會是某個項目的使用者,之後可能成爲貢獻者,接下來可能就會成爲某個項目的Committer,如果希望能夠參與這個項目未來的管理和規劃當中,會需要努力地成爲PMC Member,在這之上還會有Foundation Member,這也是最難達到境界。

下圖列出了幾篇爲大家推薦的文章,如果感興趣的話可以仔細閱讀和學習。另外,大家也看到了,中間件消息團隊在做的事情有很多,非常需要一些優秀的同學加入,感興趣的可以直接聯繫我。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章