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:大眾點評千人移動研發團隊怎樣做持續整合?
- GitLab 持續整合在 Laravel 商用專案中的應用實踐GitlabLaravel
- 端智慧在大眾點評搜尋重排序的應用實踐排序
- 大眾點評搜尋相關性技術探索與實踐
- 實踐解析:大眾點評賬號業務高可用進階之路
- 大眾點評資訊流基於文字生成的創意優化實踐優化
- 大眾點評搜尋基於知識圖譜的深度學習排序實踐深度學習排序
- 大眾點評資訊流基於文字生成的創意最佳化實踐
- 大眾點評商家爬取
- Flutter web 持續整合實踐FlutterWeb
- Jenkins持續整合 入門實踐Jenkins
- Artifactory & GitLab CI持續整合實踐Gitlab
- CI/CD 持續整合部署實踐
- 京東到家的持續整合實踐之路
- 確保使用者評價“真實可信” 大眾點評出新規制止“刷好評”
- 「持續整合實踐系列」Jenkins 2.x 搭建CI需要掌握的硬核要點Jenkins
- Practice – iOS 專案持續整合實踐(一)iOS
- Practice - iOS 專案持續整合實踐(一)iOS
- 持續交付探索與實踐(二):自動化工具鏈建設
- r確保使用者評價“真實可信” 大眾點評出新規制止“刷好評”
- QCon看點|亞馬遜雲科技可持續軟體工程實踐分享亞馬遜軟體工程
- 持續交付體系在高德的實踐歷程
- 大眾點評餐飲資料爬取(2020.11)
- 為什麼需要持續的漏洞評估?
- 持續交付探索與實踐(一):交付流水線的設計
- Flink on K8s 在京東的持續優化實踐K8S優化
- UAS:大眾點評使用者行為系統
- 持續整合持續部署持續交付_持續整合與持續部署之間的真正區別
- WWDC案例解讀:大眾點評相機直接掃描支付是怎麼實現的
- 對持續整合、 持續交付、持續部署和持續釋出的介紹
- 持續整合、持續部署、持續交付、持續釋出
- 大眾點評賬號業務高可用進階之路
- 移動APP持續交付系列之雲構建價值分析APP
- 移動影響報告:可持續發展目標(SDG)
- 大眾點評點餐小程式開發經驗 – 資料採集
- 雲效DevOps實踐-8分鐘如何快速實現持續交付dev
- Druid SQL和Security在美團點評的實踐UISQL
- 前端知識點(持續更新)前端