云音樂服務(wù)端大規(guī)模自動化升級實踐
一、背景
1. 痛點
在服務(wù)端推進(jìn)升級是一件比較困難的事情,面臨的困難點包含但不限于:
- 穩(wěn)定性風(fēng)險:組件自身兼容性的問題或不正確升級帶來的兼容性問題,可能帶來線上穩(wěn)定性風(fēng)險。
- 升級投入&成本:組件升級至少需要研發(fā)執(zhí)行升級、QA執(zhí)行測試,測試通過后再逐步灰度發(fā)布,直至全量發(fā)布。整個過程需要研發(fā)、QA投入一定的研發(fā)、測試、觀察的人力,單次升級時間至少以周為單位來計量。
- 升級推進(jìn)成本:因以上投入成本&穩(wěn)定性風(fēng)險等其他因素影響,業(yè)務(wù)研發(fā)團(tuán)隊對組件的升級意愿較低。此外,升級進(jìn)度還受團(tuán)隊排期、研發(fā)排查&解決問題的能力、多團(tuán)隊的協(xié)調(diào)參與、多角色的協(xié)調(diào)參與等因素影響。在大規(guī)模推進(jìn)升級時,需要投入大量的項目管理、協(xié)調(diào)成本。
2. 現(xiàn)狀
- 云音樂應(yīng)用規(guī)模大,且線性增長:隨著微服務(wù)的發(fā)展,服務(wù)拆分細(xì)化,疊加云音樂各業(yè)務(wù)快速發(fā)展,云音樂僅服務(wù)端應(yīng)用總數(shù)早已突破千級,當(dāng)協(xié)調(diào)多個團(tuán)隊、千級別的應(yīng)用升級時,整個升級事項的投入是巨大的。
- Jar包風(fēng)險治理率低:在目前架構(gòu)風(fēng)險巡檢中,Jar包相關(guān)的風(fēng)險因投入產(chǎn)出比低,其治理率在全部的風(fēng)險治理中幾乎墊底。Jar包的穩(wěn)定性風(fēng)險隱患隨著業(yè)務(wù)的發(fā)展而逐步增大。
- 新技術(shù)落地周期長,多版本維護(hù)成本高:當(dāng)應(yīng)用規(guī)模相對較小時,我們可以針對少量應(yīng)用,執(zhí)行技術(shù)升級,但是當(dāng)應(yīng)用規(guī)模較大時,整體推進(jìn)升級的難度較大,新技術(shù)落地的周期較長,在此過程中,多版本的維護(hù)成本高,帶來額外的人力消耗。
3. 作用
在貴州機(jī)房遷移的背景下,云音樂面臨著大批應(yīng)用升級的問題,此前一次升級中,全部團(tuán)隊基本升級完,總體用了約1個多月的時間。對此,我們研發(fā)了自動升級平臺,其核心解決升級自動化的問題。
- 在穩(wěn)定性上
通過大范圍的自動化部署/測試真實應(yīng)用,提高組件的測試樣本覆蓋,提前發(fā)現(xiàn)并解決組件可能出現(xiàn)的兼容性、穩(wěn)定性等問題。
自動解決多組件升級的問題,避免因不正確升級帶來兼容性、穩(wěn)定性問題。
- 在升級投入&成本上
對于需變更代碼的升級,通過自動升級工具,串聯(lián)自動代碼修改、自動測試環(huán)境部署、自動CI驗證,自動幫助研發(fā)完成大部分的代碼修改以及驗證工作。大部分情況下,無需測試介入,研發(fā)僅需合并代碼,執(zhí)行線上發(fā)布發(fā)布流程即可。
在升級推進(jìn)成本上
通過自動升級平臺,支持對任務(wù)的分發(fā)、中斷、配置、信息收集等等,升級過程、進(jìn)度管控完全可視化,大部分升級工作可以閉環(huán)在中心化執(zhí)行,降低了多團(tuán)隊、多角色的協(xié)作成本。
4. 使用場景
- 場景1:技術(shù)架構(gòu)升級
通過自動升級平臺,可以自動化完成大范圍應(yīng)用的技術(shù)架構(gòu)升級。例如:JDK升級、貴州機(jī)房遷移升級等場景。
- 場景2:組件風(fēng)險治理
當(dāng)組件存在風(fēng)險時,可以借助自動升級平臺,推進(jìn)完成風(fēng)險治理。
- 場景3:組件/Agent 兼容性測試
新發(fā)布組件/Agent時,目前主要在指定的測試工程里進(jìn)行兼容性測試,覆蓋場景可能存在不足,可以借助自動升級平臺完成大范圍的兼容性、穩(wěn)定性等測試。
二、技術(shù)實踐
1. 升級分類
升級分類因整體架構(gòu)的不同,升級可分為如下幾類:
圖片
- 組件升級
即傳統(tǒng)的Jar包升級,此種升級一般需要改動業(yè)務(wù)代碼才能完成,也是目前整體占比最大的一類。
- Sidecar模式升級
邊車模式,組件與業(yè)務(wù)應(yīng)用解耦,組件側(cè)的升級變更無需業(yè)務(wù)代碼變更或僅需少量變更。例如:JavaAgent、ServiceMesh等方式。
什么是Sidecar模式
Sidecar 模式是一種常見的微服務(wù)架構(gòu)模式,它通過在主應(yīng)用程序旁邊部署一個輔助應(yīng)用程序(稱為 Sidecar),來擴(kuò)展主應(yīng)用程序的功能。Sidecar 模式允許您在應(yīng)用程序旁邊添加更多功能,而無需額外第三方組件配置或修改應(yīng)用程序代碼。
此文中,我們?nèi)「鼮閺V義的Sidecar定義,將JavaAgent等作為一個輔助應(yīng)用程序看待,也被視為Sidecar模式的一種實現(xiàn)方式。
Sidecar 模式優(yōu)勢&特點
- 可擴(kuò)展性:通過添加 Sidecar 應(yīng)用程序,可以輕松地擴(kuò)展主應(yīng)用程序的功能。
- 靈活性:Sidecar 應(yīng)用程序可以獨立于主應(yīng)用程序進(jìn)行部署、升級和維護(hù)。
- 可重用性:Sidecar 應(yīng)用程序可以在多個主應(yīng)用程序之間共享,從而提高代碼重用率。
兩者的差異點和共同點
- 組件升級相較于Sidecar式升級,整體升級流程上會存在些許差異,但也存在較多重合流程節(jié)點。
- 組件升級和Sidecar式升級,均需要考慮整個升級流程中的穩(wěn)定性、兼容性、可維護(hù)性、升級規(guī)范性等問題。
2. 能力全景圖
考慮到目前云音樂微服務(wù)架構(gòu)未全面推進(jìn)sidecar化,在貴州遷移中,主要涉及組件自動升級,此文主要對組件自動升級進(jìn)行詳細(xì)闡述,而Sidecar升級能力在未來規(guī)劃中。
這部分主要介紹一下組件自動升級的能力全景,其包括底層通用能力、組件升級能力、升級任務(wù)等模塊的核心能力,整體如下圖所示:
能力全景圖.png
- 底層通用能力部分,我們主要基于Git、發(fā)布平臺、部署平臺、自動化測試平臺、代碼分析&檢索平臺、線上監(jiān)控,構(gòu)建了底層的代碼變更、測試部署、測試驗證、線上發(fā)布、結(jié)果檢測的能力。
- 組件升級能力部分,支持各類類型文件的變更。
- 在升級任務(wù)部分,我們基于自定義任務(wù)流編排和升級規(guī)則配置,支持自定義升級任務(wù)編排和多版本升級插件,以及多種維度的任務(wù)統(tǒng)計。
- 在使用場景上,自動升級平臺可用于:JDK升級、技術(shù)架構(gòu)升級、組件風(fēng)險治理、組件/Agent 兼容性測試等場景。
3. 底層通用能力&流程編排
目前主要有以下5大底層通用能力:
圖片
底層通用能力
- 升級變更。基于Git,實現(xiàn)分支創(chuàng)建/刪除、代碼提交/拉取、提交/關(guān)閉MergerRequest等能力。
- 測試部署。基于發(fā)布平臺、部署平臺、測試環(huán)境,實現(xiàn)測試環(huán)境創(chuàng)建、測試環(huán)境部署、資源釋放釋放/限流等能力。
- 測試驗證?;谧詣踊瘻y試平臺、Sonar、部署平臺,實現(xiàn)代碼CI檢測、自動化測試用例、部署驗證等能力。
- 線上發(fā)布?;诎l(fā)布平臺,實現(xiàn)灰度發(fā)布、發(fā)布流程標(biāo)準(zhǔn)化、Agent發(fā)布等能力。
- 結(jié)果檢測。基于代碼分析、線上監(jiān)控,實現(xiàn)代碼升級檢測、線上升級檢測、Agent升級檢測等能力。
以上通用能力在整合時,自動升級平臺重點做了如下方面的設(shè)計
- 流程編排。為了適用不同場景的升級,自動升級對以上通用能力進(jìn)行流程節(jié)點的細(xì)化,并支持編排。
- 資源釋放&限流。在大規(guī)模升級時,需要占用大量的資源進(jìn)行升級、部署、驗證工作,為了避免對線上環(huán)境造成影響,自動升級平臺對任務(wù)進(jìn)行了限流,并在測試驗證通過時釋放部分資源、整個任務(wù)完成時,釋放全部資源。
- 冪等&衰減重試機(jī)制。若需對底層平臺進(jìn)行讀寫輪詢操作,需要注意操作的冪等,并且衰減重試,避免產(chǎn)生臟數(shù)據(jù)或?qū)Φ讓悠脚_的請求壓力過大。
- 可觀測性設(shè)計。正常情況下的關(guān)鍵信息和異常情況下的異常信息,均需要詳細(xì)記錄,并可視化觀測,減少升級時的問題排查成本。
4. 組件升級能力
4.1 必要性
以云音樂當(dāng)前的現(xiàn)狀來看,整體距離Sidecar升級(例:ServiceMesh、Agent、MultiClassloader)仍然相差較遠(yuǎn),同時后續(xù)升級推進(jìn)JDK21、ServiceMesh也需要自動升級平臺的協(xié)助。
即使有了Sidecar,大范圍業(yè)務(wù)代碼的修改也可能是無法避免,變更代碼式的自動升級和不變更代碼的升級均需要,自動化變更代碼的方式仍然是必須的基礎(chǔ)建設(shè)。
4.2 核心特性
- 中心化操作:圈選應(yīng)用后,根據(jù)升級任務(wù)配置,自動創(chuàng)建Git分支、自動創(chuàng)建測試環(huán)境并部署、驗證。驗證通過后,提交MergerRequest
- 團(tuán)隊研發(fā)操作:合并MergerRequest,在devops發(fā)布平臺走發(fā)布流程
- 中心化操作:驗證各個應(yīng)用的Master分支升級情況、線上部署情況
4.3 能力介紹
組件自動升級插件基于OpenRewrite做了二次開發(fā)。這里簡要介紹一下OpenRewrite:
- OpenRewrite支持大規(guī)模分布式源代碼重構(gòu),以進(jìn)行框架遷移、漏洞補丁和API遷移。
- OpenRewrite基于 Lossless Semantic Trees (LST),來實現(xiàn)代碼的變更。
LST.png
- 目前除支持對普通Java項目中的java、props、properties、xml、pom.xml,也支持Spring、Micronaut、Quarkus、Jakarta、JDK17、JDK21的升級。
- 支持對變更的明細(xì)的觀測&記錄。
4.4 升級流程
圖片
組件升級默認(rèn)流程.png
以下為升級流程介紹,在此過程中加入了升級穩(wěn)定性、兼容性保障的設(shè)計
- 創(chuàng)建代碼分支。
拉取新代碼分支:不污染Master分支,不影響研發(fā)流程。
- 版本升級。
分支升級。在新的代碼分支,調(diào)用升級插件,實現(xiàn)升級
分支驗證。再次驗證分支升級的結(jié)果,避免升級錯誤。
測試部署節(jié)點。
會對各團(tuán)隊創(chuàng)建升級任務(wù)單,同時提前打通上線流程。
創(chuàng)建新的測試環(huán)境,并檢查是否部署成功。確保不影響研發(fā)流程的同時,驗證升級結(jié)果。
測試驗證節(jié)點。
觸發(fā)自動化測試用例并驗證。驗證業(yè)務(wù)邏輯是否正常。維護(hù)自動化測試用例是QA側(cè)的日常工作,若不存在自動化測試用例,流程會卡住,可通知QA側(cè)進(jìn)行維護(hù),或自行測試。
代碼CI驗證。驗證代碼CI正確。
此節(jié)點下,每步的執(zhí)行結(jié)果無論是否成功,均需直接釋放測試集群,避免在大批量升級時,占用過多的測試機(jī)器資源。當(dāng)執(zhí)行不成功時,需要將異常日志完整保存,方便問題排查。
代碼合并
當(dāng)前置所有節(jié)點通過后,可以認(rèn)為自動升級已經(jīng)成功完成了:升級、部署、驗證的工作,此時會自動發(fā)起代碼合并請求。
業(yè)務(wù)研發(fā)在Review后,將代碼合并至Master分支
合并檢測
系統(tǒng)會持續(xù)離線檢測Master分支的組件依賴情況,從而檢測是否完成升級
線上檢測
系統(tǒng)會持續(xù)離線檢測線上機(jī)器的組件依賴情況,從而檢測是否完成升級并已上線。
釋放資源
當(dāng)所有檢測通過后,認(rèn)為該升級任務(wù)已完成,會執(zhí)行各節(jié)點的釋放資源方法,釋放資源。例如:刪除代碼分支、再次檢查并釋放機(jī)器資源等。
除此之外,在每次大規(guī)模升級前,會先對指定范圍內(nèi)的應(yīng)用提前預(yù)升級,從而提前摸查該次升級中的兼容性、穩(wěn)定性問題。進(jìn)而保障升級的準(zhǔn)確性、升級推進(jìn)時的效率。
以下為系統(tǒng)實現(xiàn)示例圖:
系統(tǒng)示例圖
點擊應(yīng)用名,可查看該升級任務(wù)中各個流程節(jié)點的詳情數(shù)據(jù)。詳情數(shù)據(jù)包括成功情況、變更明細(xì)、失敗日志、失敗原因、重試間隔、最大重試次數(shù)、當(dāng)前重試次數(shù)、研發(fā)操作指引,以及一些基礎(chǔ)信息展示等。以下為系統(tǒng)示例圖:
系統(tǒng)實現(xiàn)示例圖2.png
5. 任務(wù)編排&非功能性設(shè)計
為了適用不同場景的升級,自動升級對通用能力進(jìn)行流程節(jié)點的細(xì)化,并支持編排,整體能力如下圖所示:
圖片
自定義流程編排.png
在任務(wù)編排中,我們重點做了如下設(shè)計:
- 支持任務(wù)編排。通過自定義配置實現(xiàn)節(jié)點順序編排。
- 穩(wěn)定性設(shè)計
冪等執(zhí)行。消息可能存在重復(fù)消費,因此必須支持冪等消費。
資源釋放&限流。在大規(guī)模升級時,需要占用大量的資源進(jìn)行升級、部署、驗證工作,為了避免對線上環(huán)境造成影響,自動升級平臺對任務(wù)進(jìn)行了限流,并在測試驗證通過時釋放部分資源、整個任務(wù)完成時,釋放全部資源。
- 支持按異常類型自定義重試策略。因在升級、部署驗證過程中,可能會出現(xiàn)各種異常導(dǎo)致不成功,自動升級平臺支持按照不同的異常類型來自定義重試策略,包括:重試間隔時間、最大重試次數(shù)。
- 基于MQ的消息通知機(jī)制,進(jìn)行任務(wù)節(jié)點的自動流轉(zhuǎn)、任務(wù)路由、執(zhí)行異步化。
- 過程信息、異常信息可視化。因任務(wù)依賴的系統(tǒng)/組件較多,對于過程信息、異常信息需要記錄并可視化,降低任務(wù)的理解成本、問題排查成本。
- 擴(kuò)展性設(shè)計。每個流程節(jié)點均支持異步的通知擴(kuò)展,以及同步的前置/后置Hook調(diào)用。單個流程節(jié)點分為5個階段:前置處理、前置hook、處理邏輯、后置hook、后置處理。每個階段均可獨立擴(kuò)展。
6. 任務(wù)管控&功能性設(shè)計
自動升級平臺支持任務(wù)的管控、統(tǒng)計,能力如下圖所示
升級任務(wù).png
- 支持升級范圍的圈選。除支持按照應(yīng)用、團(tuán)隊圈選應(yīng)用外,還支持按照使用的Jar來圈選應(yīng)用(即:若應(yīng)用依賴某個Jar,則會自動納入圈選)。
- 支持Jar包源&目標(biāo)版本的設(shè)置,精準(zhǔn)控制,避免升級錯誤。以下為示例圖:
圖片
- 與自動升級插件聯(lián)動,支持升級規(guī)則的配置、升級插件版本的配置,支持不同的任務(wù)可執(zhí)行不同的升級規(guī)則。
圖片
- 支持升級任務(wù)編排。每個任務(wù)可獨立定制自己的任務(wù)流程。
- 支持任務(wù)的重試、跳過、關(guān)閉(包含資源釋放)、重新開始等管控功能。
- 支持任務(wù)統(tǒng)計。
支持團(tuán)隊、應(yīng)用、任務(wù)階段維度的統(tǒng)計。
支持結(jié)果檢測統(tǒng)計。
支持執(zhí)行時長、進(jìn)度維度的統(tǒng)計。
三、運行數(shù)據(jù)
1. 支持事項
自動升級平臺在近半年的時間里,支撐了貴州機(jī)房遷移測試環(huán)境演練升級、貴州機(jī)房遷移全量應(yīng)用升級、網(wǎng)關(guān)ZK拆分升級三大事項。
2. 運行數(shù)據(jù)
- 一次性升級成功率約50%。在小范圍、標(biāo)準(zhǔn)化的應(yīng)用升級任務(wù)中,一次性升級成功率較高,在貴州機(jī)房全量應(yīng)用升級中,一次性升級成功率約在50%左右。未能一次性升級成功的應(yīng)用,研發(fā)也可借助升級平臺進(jìn)行問題排查&解決,提升升級效率。
- 貴州遷移約節(jié)省人日約500人日,效率提升約83%。自動升級平臺按照1000個應(yīng)用且僅升級一次保守統(tǒng)計,總體節(jié)省人力約500人日,升級效率提升約83%
節(jié)約人力:0.6d(研發(fā)+QA升級并驗證單個應(yīng)用的平均耗時) * 1000(應(yīng)用數(shù)) - 0.1d(自動升級平臺升級并驗證單個應(yīng)用的平均耗時) * 1000(應(yīng)用數(shù)) = 500d
效率提升 :500/600 = 83%
- 數(shù)據(jù)對比如下:
圖片
數(shù)據(jù)對比.png
3. 問題總結(jié)
對于未能一次性升級成功的原因,歸納主要有:
- 應(yīng)用組件版本過于陳舊,不符合升級最低版本要求。
因版本跨度較大,有太大兼容性問題,自動升級平臺不再予以支持。此部分應(yīng)用在貴州機(jī)房遷移過程中,也大都不再升級,而是由各業(yè)務(wù)自行遷移。
- 測試環(huán)境配置維護(hù)不足,自動部署成功率低。
測試環(huán)境配置維護(hù)不足主要體現(xiàn)在:應(yīng)用的構(gòu)建、發(fā)布配置上,例如:健康檢查未配置、啟動類設(shè)置錯誤、內(nèi)存參數(shù)設(shè)置不合理、期望啟動時間設(shè)置不合理等等。
組件依賴的使用方式多樣,也存在非標(biāo)準(zhǔn)的使用方式,升級工具覆蓋不足。
非腳手架的老應(yīng)用,組件依賴的的使用方式較為多樣,也存在非標(biāo)準(zhǔn)的使用方式。
升級工具基于OpenRewrite進(jìn)行二次開發(fā),從實際運行的效果來看,OpenRewrite的一些開源規(guī)則仍有可完善的空間。
新發(fā)布組件,因帶來新的依賴變更或依賴版本變更,帶來新的兼容性問題。
例如:dts-sdk,在3.x除部分類路徑、類名發(fā)生變更外,又新引入了servlet-api、jsp-api、logback、commons-beanutils-core等Jar包依賴,與云音樂技術(shù)中心的應(yīng)用、組件存在普遍的不兼容問題。
查詢的啟動結(jié)果不準(zhǔn)確。
部分應(yīng)用可能因啟動時間過長、多次自動重啟,導(dǎo)查詢的啟動結(jié)果不準(zhǔn)確
少量應(yīng)用未接入自動化測試用例。
四、未來展望
以下為能力規(guī)劃全景圖:
圖片
未來規(guī)劃全景圖.png
- 提升一次性升級成功率。
- 增加Sidecar升級能力的支持。
- 支持組件發(fā)布、版本管理、風(fēng)險治理與自動升級的聯(lián)動。降低組件自身風(fēng)險、同時提升組件側(cè)、治理側(cè)的效率,形成整體的閉環(huán)
圖片