線上環(huán)境大規(guī)模RocketMQ集群不停機優(yōu)雅升級實踐
本文轉(zhuǎn)載自微信公眾號「 中間件興趣圈」,作者丁威 。轉(zhuǎn)載本文請聯(lián)系 中間件興趣圈公眾號。
RocketMQ集群的升級方案、落地實施就自然而然的落到了我的頭上,本文不僅要介紹一下筆者是如何升級的,更想展示作為一名架構(gòu)師,處理這些問題的方法論,展示大廠架構(gòu)師的工作日常。
溫馨提示:關于ACL相關的內(nèi)容,后續(xù)文章會單獨分享從4.1.0版本升級到4.8并開啟ACL的曲折經(jīng)歷。
1、版本升級的迫切性
說來慚愧,作為RocketMQ社區(qū)優(yōu)秀布道師,筆者所在公司的RocketMQ服務端版本竟然還是4.1.0,RocketMQ在4.4.0版本之前是不支持ACL(訪問控制),對應生產(chǎn)環(huán)境中任意一臺機器都可以訂閱任意topic,在任意一臺生產(chǎn)應用服務器都可以安裝一個rocketmq-console,從而控制整個集群,擁有刪除主題、刪除消費組的權(quán)限,想想是不是后背發(fā)涼.
2、升級方案
2.1 確定升級到的版本
翻開RocketMQ升級日志,RocketMQ在4.4.0版本正式引入了ACL機制,故版本至少要升級到4.4.0,在業(yè)界使用開源版本有一個不成文的規(guī)則:通常不要使用最新的版本,不要充當小白鼠。
但RocketMQ可以算是一個特殊。
通過仔細瀏覽RocketMQ的版本變更記錄,我們不難發(fā)現(xiàn)RocketMQ Client 相關的變更非常少,即與用戶關系緊密的消息發(fā)送、消息消費這塊的代碼非常的穩(wěn)定,理論上基本不存在兼容性問題。并且每一個版本都修復了一些重大的BUG,性能提升也比較明顯,故筆者這次決定“冒天下之大不韙”,決定將幫升級到最新版本4.8.0。
在這里在啰嗦一些,簡單介紹一下RocketMQ幾個具有里程杯意義的版本。
- RocketMQ4.3.0正式引入了事務消息,如果大家希望使用事務消息,其版本最低建議為 4.6.1。
- RocketMQ4.4.0引入了ACL、消息軌跡,如果需要使用這些功能,其版本最低建議為 4.7.0。
- RocketMQ4.5.0引入了多副本(主從切換),其版本建議使用4.7.0。
- RocketMQ4.6.0引入了請求-響應模型。
2.2 升級思路
版本升級的基本要求:業(yè)務不能停機,即要做到對業(yè)務無感知的升級。
如果機器足夠的備用機器,最佳的版本遷移方案應該是先擴容再縮容,其示例圖如下:
其主要的思路是先對Broker進行擴容,加入兩臺高版本的Broker服務器,加入到集群中,然后關閉低版本Broker的寫權(quán)限,待消息過期后,將低版本移除,最后升級NameServer,完成不停機的在線遷移。
由于此次升級需要在半個月左右的時間內(nèi)將RocketMQ集群所有的節(jié)點全部升級,無法提供這么多冷備節(jié)點,故先擴容、再縮容無法滿足本次需求,本次只能基于已有的機器進行升級。
能否直接升級Broker端代碼,但高版本的Broker直接使用低版本的Broker存儲目錄,即直接升級軟件,其示例圖如下:
核心思想是先停止老版本的Broker,然后使用新版本啟動Broker,但使用舊的配置文件。
有了思路,接下來就是要驗證方案的可行性。
2.3 方案驗證
理論歸理論,在生產(chǎn)環(huán)境做任何變更之前,必須有充分的測試驗證,版本升級重點需要驗證兼容性問題。
2.2.1 服務端版本兼容性驗證
搭建一個上述MQ集群,其核心要點:
- 高版本的Broker是否能向低版本的NameServer注冊路由
- 低版本的Broker是否能向高版本的NameServer注冊路由
通過rocketmq-console,去創(chuàng)建多個個topic,看看其路由信息是否正確,經(jīng)驗證,符合預期。
2.2.2 客戶端與服務端兼容性驗證
RocketMQ的客戶端API其實比較單一,無非就是消息發(fā)送、批量發(fā)送,消息消費,由于4.1版本不支持事務消息,這次升級甚至都無需驗證事務消息,驗證的要點:
- 低版本的客戶端是否能正常向高版本Broker發(fā)送消息,消費消息
- 高版本的客戶端是否能向低版本的Broker發(fā)送消息,消費消息
測試案例來自哪,其實都不需要我們自己寫,直接用官方的Demo即可,其代碼截圖如下:
客戶端驗證在真正實施過程中,其實比服務端之間的驗證要復雜的多,由于各個項目組使用的客戶端版本不一,甚至有些項目組會使用c++、Python等其他非Java客戶端,如何精確找到該集群中所有客戶端的連接信息(客戶端版本、語言類型)至關重要。
官方提供的版本,對消費組的連接信息還是支持的比較友好,我們可以通過寫腳本,先查詢系統(tǒng)中所有的消費組,然后遍歷每一個消費組,可以查詢這些消費組的IP地址、客戶端版本、使用的語言等信息,但開源版本對生產(chǎn)者支持的不友好,沒有一個可獲取所有發(fā)送者相關的接口。
獲取消費組消費端的連接方式如下圖所示:
故我們采取的方式,主要是基于消費組失敗客戶端類型,本次升級過程中,我也對RocketMQ做了一些定制化開發(fā),可方便獲取所有發(fā)送方的鏈接信息,后續(xù)會已提交PR的方式貢獻給官方。
2.2.3 Broker端存儲格式驗證
由于沒有空閑資源,本次要使用的升級方式是直接升級軟件,但新老版本共用存儲目錄,基于RocketMQ的消息存儲協(xié)議,從4.0.0版本之后就一直沒有變化,其驗證的關鍵點如下:
- 4.8.0版本是否可以直接使用4.1.0生成的存儲文件(commitlog等文件)
- 4.1.0版本是否可以直接使用4.8.0生成的存儲文件
為什么需要驗證4.1.0版本能兼容4.8.0呢?因為如果升級失敗,需要回滾,如果4.1.0版本不能兼容4.8.0的話,會讓你沒有退路,這在架構(gòu)設計中是絕對不允許的。
經(jīng)過驗證發(fā)現(xiàn),存儲文件是相互兼容的。
2.2.4 測試環(huán)境驗證
經(jīng)過上面三步的驗證,已經(jīng)可以進行升級了,但升級之前,還要在測試環(huán)境穩(wěn)定運行一天,可以將測試環(huán)境升級成如下架構(gòu):
即不同版本的混搭模式,接受測試環(huán)境所有應用服務器的驗證,如果測試環(huán)境運行沒有問題,即可在生產(chǎn)環(huán)境進行升級。
2.4 實施方案
有了上面升級方案,并且已經(jīng)做了充分的驗證,是可以在生產(chǎn)環(huán)境執(zhí)行了,在執(zhí)行之前,需要對理論設計輸出可執(zhí)行可落地的實施方案,實施方案必須要包括回滾操作,并且這個回滾操作一定要比較容易執(zhí)行,否則你的方案一定是不那么可靠的。
接下來重點闡述一下實施過程中一些關鍵步驟,整個升級步驟才有滾動升級,即逐臺升級。
1、關閉一個Broker的寫權(quán)限
關閉Broker寫權(quán)限,讓應用將流量平滑遷移到其他節(jié)點,這樣可以有效避免在對該機器進行重啟時對業(yè)務造成的影響。
- sh ./mqadmin updateBrokerConfig -b 192.168.x.x:10911 -n 192.168.xx.xx:9876 -k brokerPermission -v 4
2、帶Broker寫入、消費tps接近0時,關閉broker
- ps -ef | grep java
- kill pid
3、使用新版本啟動Broker
注意,此過程使用的配置文件為老版本的配置,故此時并沒有開啟寫權(quán)限,啟動并不會對客戶端消息寫入造成影響。
4、開啟寫權(quán)限
待新版本啟動成功后,既可以開啟寫權(quán)限
- sh ./mqadmin updateBrokerConfig -b 192.168.xx.xx:10911 -n 192.168.xx.xx:9876 -k brokerPermission -v 6
觀察流量。
重復上述步驟即可完成Broker的升級。
關于Nameserver的升級就更加容易了,采用滾動升級,kill掉老版本的nameserver,在原機器上啟動新版本的nameserver即可。