MCI:移动持续集成在大众点评的实践
一、背景
美團是全球最大的互聯網+生活服務平臺,為3.2億活躍用戶和500多萬的優質商戶提供一個連接線上與線下的電子商務服務。秉承“幫大家吃得更好,生活更好”的使命,我們的業務覆蓋了超過200個品類和2800個城區縣網絡,在餐飲、外賣、酒店旅游、麗人、家庭、休閑娛樂等領域具有領先的市場地位。
隨著各業務的蓬勃發展,大眾點評移動研發團隊從當初各自為戰的“小作坊”已經發展成為可以協同作戰的、擁有千人規模的“正規軍”。我們的移動項目架構為了適應業務發展也發生了天翻地覆的變化,這對移動持續集成提出更高的要求,而整個移動研發團隊也迎來了新的機遇和挑戰。
二、問題與挑戰
當前移動客戶端的組件庫超過600個,多個移動項目的代碼量達到百萬行級別,每天有幾百次的發版集成需求。保證近千名移動研發人員順利進行開發和集成,這是我們部門的重要使命。但是,前進的道路從來都不是平坦的,在通向目標的大道上,我們還面臨著很多問題與挑戰,主要包括以下幾個方面:
項目依賴復雜
上圖僅僅展示了我們移動項目中一小部分組件間的依賴關系,可以想象一下,這600多個組件之間的依賴關系,就如同一個城市復雜的道路交通網讓人眼花繚亂。這種組件間錯綜復雜的依賴關系也必然會導致兩個嚴重的問題,第一,如果某個業務需要修改代碼,極有可能會影響到其它業務,牽一發而動全身,進而會讓很多研發同學工作時戰戰兢兢,做項目更加畏首畏尾;第二,管理這些組件間繁瑣的依賴關系也是一件令人頭疼的事情,現在平均每個組件的依賴數有70多個,最多的甚至達到了270多個,如果依靠人工來維護這些依賴關系,難如登天。
研發流程瑣碎
移動研發要完成一個完整功能需求,除了代碼開發以外,需要經歷組件發版、組件集成、打包、測試。如果測試發現Bug需要進行修復,然后再次經歷組件發版、組件集成、打包、測試,直到測試通過交付產品。研發同學在整個過程中需要手動提交MR、手動升級組件、手動觸發打包以及人工實時監控流程的狀態,如此研發會被頻繁打斷來跟蹤處理過程的銜接,勢必嚴重影響開發專注度,降低研發生產力。
構建速度慢
目前大眾點評的iOS項目構建時間,從兩年前的20分鐘已經增長到現在的60分鐘以上,Android項目也從5分鐘增長到11分鐘,移動項目構建時間的增長,已經嚴重影響了移動端開發集成的效率。而且隨著業務的快速擴張,項目代碼還在持續不斷的增長。為了適應業務的高速發展,尋求行之有效的方法來加快移動項目的構建速度,已經變得刻不容緩。
App質量保證
評價App的性能質量指標有很多,例如:CPU使用率、內存占用、流量消耗、響應時間、線上Crash率、包體等等。其中線上Crash直接影響著用戶體驗,當用戶使用App時如果發生閃退,他們很有可能會給出“一星”差評;而包體大小是影響新用戶下載App的重要因素,包體過大用戶很有可能會對你的App失去興趣。因此,降低App線上Crash率以及控制App包體大小是每個移動研發都要追求的重要目標。
項目依賴復雜、研發流程瑣碎、構建速度慢、App質量保證是每個移動項目在團隊、業務發展壯大過程中都會遇到的問題,本文將根據大眾點評移動端多年來積累的實踐經驗,一步步闡述我們是如何在實戰中解決這些問題的。
三、MCI架構
MCI(Mobile continuous integration)是大眾點評移動端團隊多年來實踐總結出來的一套行之有效的架構體系。它能實際解決移動項目中依賴復雜、研發流程瑣碎、構建速度慢的問題,同時接入MCI架構體系的移動項目能真正有效實現App質量的提升。
MCI完整架構體系如下圖所示:
MCI架構體系包含移動CI平臺、流程自動化建設、靜態檢查體系、日志監控&分析、信息管理配置,另外MCI還采取二進制集成等措施來提升MCI的構建速度。
構建移動CI平臺
我們通過構建移動CI平臺,來保證移動研發在項目依賴極其復雜的情況下,也能互不影響完成業務研發集成;其次我們設計了合理的CI策略,來幫助移動研發人員走出令人望而生畏的依賴關系管理的“泥潭”。
流程自動化建設
在構建移動CI平臺的基礎上,我們對MCI流程進行自動化建設來解決研發流程瑣碎問題,從而解放移動研發生產力。
提升構建速度
在CI平臺保證集成正確性的情況下,我們通過依賴扁平化以及優化集成方式等措施來提升MCI的構建速度,進一步提升研發效率。
靜態檢查體系
我們建立一套完整自研的靜態檢查體系,針對移動項目的特點,MCI上線全方位的靜態檢查來促進App質量的提升。
日志監控&分析
我們對MCI體系的完整流程進行日志落地,方便問題的追溯與排查,同時通過數據分析來進一步優化MCI的流程以及監控移動App項目的健康狀況。
信息管理配置
最后,為了方便管理接入MCI的移動項目,我們建設了統一的項目信息管理配置平臺。
接下來,我們將依次詳細探討MCI架構體系是如何一步步建立,進而解決我們面臨的各種問題。
四、構建移動CI平臺
4.1 搭建移動CI平臺
我們對目前業內流行的CI系統,如:Travis CI、 CircleCI、Jenkins、Gitlab CI調研后,針對移動項目的特點,綜合考慮代碼安全性、可擴展性及頁面可操作性,最終選擇基于Gitlab CI搭建移動持續集成平臺,當然我們也使用Jenkins做一些輔助性的工作。MCI體系的CI核心架構如下圖所示:
名詞解釋:
- Gitlab CI:Gitlab CI是GitLab Continuous Integration(Gitlab持續集成)的簡稱。
- Runner:Runner是Gitlab CI提供注冊CI服務器的接口。
- Pipeline:可以理解為流水線,包含CI不同階段的不同任務。
- Trigger:觸發器,Push代碼或者提交Merge Request等操作會觸發相應的觸發器以進入下一流程。
該架構的優勢是可擴展性強、可定制、支持并發。首先CI服務器可以任意擴展,除了專用的服務器可以作為CI服務器,普通個人PC機也可以作為CI服務器(缺點是性能比服務器差,任務執行時間較長);其次每個集成任務的Pipeline是支持可定制的,托管在MCI的集成項目可以根據自身需求定制與之匹配的Pipeline;最后,每個集成項目的任務執行是可并發的,因此各業務線間可以互不干擾的進行組件代碼集成。
4.2 CI流程設計
一次完整的組件集成流程包含兩個階段:組件庫發版和向目標App工程集成。如下圖所示:
第一階段,在日常功能開發完畢后,研發提PR到指定分支,在對代碼進行Review、組件庫編譯及靜態檢查無誤后,自動發版進入組件池中。所有進入組件池中的組件均可以在不同App項目中復用。
第二階段,研發根據需要將組件合入指定App工程。組件A本身的正確性已經在第一階段的組件庫發版中驗證,第二階段是檢查組件A的改變是否對目標App中原有依賴它的其它組件造成影響。所以首先需要分析組件A被目標App中哪些組件所依賴,目標App工程按照各自的準入標準,對合入的組件庫進行編譯和靜態分析,待檢查無誤后,最終合入發布分支。
通過組件發版和集成兩階段的CI流程,組件將被正確集成到目標項目中。而對于存在問題的組件則會阻擋在項目之外,因此不會影響其它業務的正常開發和發版集成,各業務研發流程獨立可控。
4.3 設計合理的CI策略
組件的發版和集成能否通過CI檢查,取決于組件當前的依賴以及組件本身是否與目標項目兼容。移動研發需要對組件當前依賴有足夠的了解才能順利完成發版集成,為了減小組件依賴管理的復雜度,我們設計了合理的發版集成策略來幫助移動研發走出繁瑣的版本依賴管理的困境。
組件集成策略
每個組件都有自己的依賴項,不同組件可能會依賴同一個組件,組件向目標項目集成過程中會面臨如下一些問題:
- 版本集成沖突:組件在集成過程中某個依賴項與目標項目中現有依賴的版本號存在沖突。
- App測試包不穩定:組件依賴項的版本發生變化導致在不同時刻打出不同依賴項的App測試包。
頻繁的版本集成沖突會導致業務協同開發集成效率低下,App測試包的不穩定性會給研發追蹤問題帶來極大的困擾。問題的根源在于目標項目使用每個組件的依賴項來進行集成。因此我們通過在集成項目中顯示指定組件版本號以及禁止動態依賴的方式,保證了App測試包的穩定性和可靠性,同時也解決了組件版本集成沖突問題。
組件發版策略
組件向組件池發版也一樣會涉及依賴項的管理,簡單粗暴的方法是指定所有依賴項的版本號,這樣做的好處是直觀明了,但研發需要對不同版本依賴項的功能有足夠的了解。正如組件集成策略中所述,集成項目中每個組件的版本都是顯示指定并且唯一確定的,組件中指定依賴項的版本號在集成項目中并不起作用。所以我們在組件發版時采用自動依賴組件池中最新版本的方式。這樣設計的好處在于:
- 避免移動研發對版本依賴關系的處理。
- 給基礎組件的變更迭代提供了強有力的推動機制。
當基礎組件庫的接口和設計發生較大變化時,可以強有力的推動業務層組件做相應適配,保證了在高度解耦的項目架構下保持高度的敏捷性。但這種能力不能濫用,需要根據業務迭代周期合理安排,并做好提前通知動員工作。
五、流程自動化建設
研發流程瑣碎的主要原因是研發需要人工參與持續集成中每一步過程,一旦我們把移動研發從持續集成過程中解放出來,自然就能提高研發生產力。我們通過項目集成發布流程自動化以及優化測試包分發來優化MCI流程。
項目集成流程托管
研發流程中的組件發版、組件集成與App打包都是持續集成中的標準化流程,我們通過流程托管工具來完成這幾個步驟的自動銜接,研發同學只需關注代碼開發與Bug修復。
流程托管工具實現方案如下:
- 自動化流程執行:通過托管隊列實現任務自動化順序執行,webhook實現流程狀態的監聽。
- 關鍵節點通知:在關鍵性節點流程執行成功后發送通知,讓研發對流程狀態了然于胸。
- 流程異常通知:一旦持續集成流程執行異常,例如項目編譯失敗、靜態檢查沒通過等,第一時間通知研發及時處理。
打包發布流程托管
無論iOS還是Android,在發布App包到市場前都需要做一系列處理,例如iOS需要導出ipa包進行備份,保存符號表來解析線上Crash,以及上傳ipa包到iTC(iTunes Connect);而Android除了包備份,保存Mapping文件解析線上Crash外,還要發布App包到不同的渠道,整個打包發布流程更加復雜繁瑣。
在沒有MCI流程托管以前,每到App發布日,研發同學就如臨大敵守在打包機器前,披荊斬棘,過五關斬六將,直到所有App包被“運送”到指定地點,搞得十分疲憊。如同項目集成流程托管一樣,我們把整個打包發布流程做了全流程托管,無人值守的自動打包發布方式解放了研發同學,研發同學再也不用每次都披星戴月,早出晚歸,跪鍵盤了(捂臉)。
包分發流程建設
對于QA和研發而言,上面的場景是否似曾相識。Bug是QA與研發之間溝通的橋梁,但由于缺乏統一的包管理和分發,這種模糊的溝通導致難以快速定位和追溯發生問題的包。為了減少QA和研發之間的無效溝通以及優化包分發流程,我們亟需一個平臺來統一管理分發公司內部的App包,于是MCI App應運而生。
MCI App提供如下功能:
- 查看下載安裝不同類型不同版本的App。
- 查看App包的基礎信息(打包者、打包耗時、包版本、代碼提交commit點等)。
- 查看App包當前版本集成的所有組件庫信息。
- 查看App包體占用情況。
- 查詢App發版時間計劃。
- 分享安裝App包下載鏈接。
未來MCI App還會支持查詢項目集成狀態以及App發布提醒、問題反饋,整合移動研發全流程。
六、提升構建速度
移動項目在構建過程中最為耗時的兩個步驟分別為組件依賴計算和工程編譯。
組件依賴計算
組件依賴計算是根據項目中指定的集成組件計算出所有相關的依賴項以及依賴版本,當項目中集成組件較多的時候,遞歸計算依賴項以及依賴版本是一件非常耗時的操作,特別是還要處理相關的依賴沖突。
工程編譯
工程編譯時間是跟項目工程的代碼量成正比的,集團業務在快速發展,代碼量也在快速的膨脹。
為了提升項目構建速度,我們通過依賴扁平化的方法來徹底去掉組件依賴計算耗時,以及通過優化項目集成方式的手段來減少工程編譯時間。
依賴扁平化
依賴扁平化的核心思想是事先把依賴項以及依賴版本號進行顯示指定,這樣通過固定依賴項以及依賴版本就徹底去掉了組件依賴計算的耗時,極大的提高了項目構建速度。與此同時,依賴扁平化還額外帶來了下面的好處:
- 減輕研發依賴關系維護的負擔。
- App項目更加穩定,不會因為依賴項的自動升級出現問題。
優化集成方式
通常組件代碼都是以源碼方式集成到目標工程,這種集成方式的最大缺點是編譯速度慢,對于上百萬行代碼的App,如果采用源碼集成的方式,工程編譯時間將超過40分鐘甚至更長,這個時間,顯然會令人崩潰。
使用源碼集成
使用二進制集成
實際上組件代碼還可以通過二進制的方式集成到目標工程:
相比源碼方式集成,組件的二進制包都是預先編譯好的,在集成過程中只需要進行鏈接無需編譯,因此二進制集成的方式可以大幅提升項目編譯速度。
二進制集成優化
為了進一步提高二進制集成效率,我們還做了幾件小事:
(1)多線程下載
盡管二進制集成的方式能減少工程編譯時間,但二進制包還是得從遠端下載到CI服務器上。我們修改了默認單線程下載的策略,通過多線程下載二進制包提升下載效率。
(2)二進制包緩存
研發在MCI上觸發不同的集成任務,這些集成任務間除了升級的組件,其它使用的組件二進制包大部分是相同的,因此我們在CI服務器上對組件二進制包進行緩存以便不同任務間進行共享,進一步提升項目構建速度。
二進制集成成果
我們在MCI中采用二進制集成并且經過一系列優化后,iOS項目工程的編譯時間比原來減少60%,Android項目也比原來減少接近50%,極大地提升了項目構建效率。
七、靜態檢查體系
除了完成日常需求開發,提高代碼質量是每個研發的必修課。如果每一位移動研發在平時開發中能嚴格遵守移動編程規范與最佳實踐,那很多線上問題完全可以提前避免。事實上僅僅依靠研發自覺性,難以長期有效的執行,我們需要把這些移動編程規范和最佳實踐切實落地成為靜態檢查強制執行,才能有效的將問題扼殺在搖籃之中。
靜態檢查基礎設施
靜態檢查最簡單的方式是文本匹配,這種方式檢查邏輯簡單,但存在局限性。比如編寫的靜態檢查代碼維護困難,再者文本匹配能力有限對一些復雜邏輯的處理無能為力。現有針對Objective-C和Java的靜態分析工具也有不少,常見的有:OCLint、FindBugs、CheckStyle等等,但這些工具定制門檻較高。為了降低靜態檢查接入成本,我們自主研發了一個適應MCI需求的靜態分析框架–Hades。
Hades的特點:
- 完全代碼語義理解
- 具備全局分析能力
- 支持增量分析
- 接入成本低
Hades的核心思想是對源碼生成的AST(Abstract Syntax Tree)進行結構化數據的語義表達,在此基礎上我們就可以建立一系列靜態分析工具和服務。作為一個靜態分析框架,Hades并不局限于Lint工具的制作,我們也希望通過這種結構化的語義表達來對代碼有更深層次的理解。因此,我們可以借助文檔型數據庫(如:CouchDB、MongoDB等)建立項目代碼的語義模型數據庫,這樣我們能夠通過JS的Map-Reduce建立視圖從而快速檢索我們需要查找的內容。關于Hades的技術實現原理我們將在后續的技術Blog中進行詳細闡述,敬請期待。
MCI靜態檢查現狀
目前MCI已經上線了覆蓋代碼基本規范、非空特性、多線程最佳實踐、資源合法性、啟動流程管控、動態行為管控等20多項靜態檢查,這些靜態檢查切實有效地促進了App代碼質量的提高。
八、日志監控&分析
MCI作為大眾點評移動端持續集成的重要平臺,穩定高效是要達成的第一目標,日志監控是推動MCI走向穩定高效的重要手段。我們對MCI全流程的日志進行落地,方便問題追溯與排查,以下是部分線上監控項。
流程時間監控分析
通過監控分析MCI流程中每一步的執行時間,我們可以進行針對性的優化以提高集成速度。
異常流程監控分析
我們會對異常流程進行監控并且通知流程發起者,同時我們會對失敗次數較多的Job分析原因。一部分CI環境或者網絡問題MCI可以自動解決,而其它由于代碼錯誤引起的異常MCI會引導移動研發進行問題的排查與解決。
包體監控分析
我們對包體總大小、可執行文件以及圖片進行全方面的監控,包體變化的趨勢一目了然,對于包體的異常變化我們可以第一時間感知。
除此之外,我們還對MCI集成成功率、二進制覆蓋率等方面做了監控,做到對MCI全流程了然于胸,讓MCI穩定高效的運行。
九、信息管理配置
目前MCI平臺已經接入公司多個移動項目,為了接入MCI的項目進行統一方便的信息管理,我們建設了MCI信息管理平臺——摩卡(Mocha)。Mocha平臺的功能包含項目信息管理、配置靜態檢查項以及組件發版集成查詢。
項目信息管理
Mocha平臺負責注冊接入MCI項目的基本信息,包含項目地址、項目負責人等,同時對各個項目的成員進行權限管理。
配置靜態檢查項
MCI支持不同項目自定義不同的靜態檢查項,在Mocha平臺上可以完成項目所需靜態檢查項的定制,同時支持靜態檢查白名單的配置審核。
組件發版集成查詢
Mocha平臺支持組件歷史發版集成的記錄查詢,方便問題的排查與追溯。
作為移動集成項目的可視化配置系統,Mocha平臺是MCI的一個重要補充。它使得移動項目接入MCI變得簡單快捷,未來Mocha平臺還會加入更多的配置項。
十、總結與展望
本文從大眾點評移動項目業務復雜度出發,詳細介紹了構建穩定高效的移動持續集成系統的思路與最佳實踐方案,解決項目依賴復雜所帶來的問題,通過依賴扁平化以及二進制集成提升構建速度。在此基礎上,通過自研的靜態檢查基礎設施Hades降低靜態檢查準入的門檻,幫助提升App質量;最后MCI提供的全流程托管能力能顯著提高移動研發生產力。
目前MCI為iOS、Android原生代碼的項目集成已經提供了相當完善的支持。此外,MCI還支持Picasso項目的持續集成,Picasso是大眾點評自研的高性能跨平臺動態化框架,專注于橫跨iOS、Android、Web、小程序四端的動態化UI構建。當然移動端原生項目的持續集成和動態化項目的持續集成有共通也有很多不同之處。未來MCI將在移動工程化領域進一步探索,為移動端業務蓬勃發展保駕護航。
作者簡介
- 智聰,大眾點評iOS技術專家,專注于移動工具鏈開發,對移動持續集成、靜態分析平臺建設有深刻理解和豐富的實踐經驗。
- 邢軼,大眾點評Android技術專家,專注于移動持續集成、靜態分析、靜態化等App基礎設施建設。
團隊介紹
大眾點評移動研發中心,Base上海,為美團提供移動端底層基礎設施服務,包含網絡通信、移動監控、推送觸達、動態化引擎、移動研發工具等。同時團隊還承載流量分發、UGC、內容生態、個人中心等業務研發工作,長年虛位以待專注于移動端研發的各路英雄豪杰。歡迎投遞簡歷:dawei.xing#dianping.com。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的MCI:移动持续集成在大众点评的实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WMRouter:美团外卖Android
- 下一篇: 实时数据产品实践——美团大交通战场沙盘