美團是全球最大的互聯網+生活服務平臺,爲3.2億活躍用戶和500多萬的優質商戶提供一個鏈接線上與線下的電子商務服務。秉承「幫你們吃得更好,生活更好」的使命,咱們的業務覆蓋了超過200個品類和2800個城區縣網絡,在餐飲、外賣、酒店旅遊、麗人、家庭、休閒娛樂等領域具備領先的市場地位。html
隨着各業務的蓬勃發展,大衆點評移動研發團隊從當初各自爲戰的「小做坊」已經發展成爲能夠協同做戰的、擁有千人規模的「正規軍」。咱們的移動項目架構爲了適應業務發展也發生了天翻地覆的變化,這對移動持續集成提出更高的要求,而整個移動研發團隊也迎來了新的機遇和挑戰。web
當前移動客戶端的組件庫超過600個,多個移動項目的代碼量達到百萬行級別,天天有幾百次的發版集成需求。保證近千名移動研發人員順利進行開發和集成,這是咱們部門的重要使命。可是,前進的道路歷來都不是平坦的,在通向目標的大道上,咱們還面臨着不少問題與挑戰,主要包括如下幾個方面:數據庫
上圖僅僅展現了咱們移動項目中一小部分組件間的依賴關係,能夠想象一下,這600多個組件之間的依賴關係,就如同一個城市複雜的道路交通網讓人眼花繚亂。這種組件間錯綜複雜的依賴關係也必然會致使兩個嚴重的問題,第一,若是某個業務須要修改代碼,極有可能會影響到其它業務,牽一髮而動全身,進而會讓不少研發同窗工做時戰戰兢兢,作項目更加畏首畏尾;第二,管理這些組件間繁瑣的依賴關係也是一件使人頭疼的事情,如今平均每一個組件的依賴數有70多個,最多的甚至達到了270多個,若是依靠人工來維護這些依賴關係,難如登天。編程
移動研發要完成一個完整功能需求,除了代碼開發之外,須要經歷組件發版、組件集成、打包、測試。若是測試發現Bug須要進行修復,而後再次經歷組件發版、組件集成、打包、測試,直到測試經過交付產品。研發同窗在整個過程當中須要手動提交MR、手動升級組件、手動觸發打包以及人工實時監控流程的狀態,如此研發會被頻繁打斷來跟蹤處理過程的銜接,勢必嚴重影響開發專一度,下降研發生產力。小程序
目前大衆點評的iOS項目構建時間,從兩年前的20分鐘已經增加到如今的60分鐘以上,Android項目也從5分鐘增加到11分鐘,移動項目構建時間的增加,已經嚴重影響了移動端開發集成的效率。並且隨着業務的快速擴張,項目代碼還在持續不斷的增加。爲了適應業務的高速發展,尋求行之有效的方法來加快移動項目的構建速度,已經變得刻不容緩。緩存
評價App的性能質量指標有不少,例如:CPU使用率、內存佔用、流量消耗、響應時間、線上Crash率、包體等等。其中線上Crash直接影響着用戶體驗,當用戶使用App時若是發生閃退,他們頗有可能會給出「一星」差評;而包體大小是影響新用戶下載App的重要因素,包體過大用戶頗有可能會對你的App失去興趣。所以,下降App線上Crash率以及控制App包體大小是每一個移動研發都要追求的重要目標。安全
項目依賴複雜、研發流程瑣碎、構建速度慢、App質量保證是每一個移動項目在團隊、業務發展壯大過程當中都會遇到的問題,本文將根據大衆點評移動端多年來積累的實踐經驗,一步步闡述咱們是如何在實戰中解決這些問題的。服務器
MCI(Mobile continuous integration)是大衆點評移動端團隊多年來實踐總結出來的一套行之有效的架構體系。它能實際解決移動項目中依賴複雜、研發流程瑣碎、構建速度慢的問題,同時接入MCI架構體系的移動項目能真正有效實現App質量的提高。網絡
MCI完整架構體系以下圖所示:多線程
MCI架構體系包含移動CI平臺、流程自動化建設、靜態檢查體系、日誌監控&分析、信息管理配置,另外MCI還採起二進制集成等措施來提高MCI的構建速度。
咱們經過構建移動CI平臺,來保證移動研發在項目依賴極其複雜的狀況下,也能互不影響完成業務研發集成;其次咱們設計了合理的CI策略,來幫助移動研發人員走出使人望而生畏的依賴關係管理的「泥潭」。
在構建移動CI平臺的基礎上,咱們對MCI流程進行自動化建設來解決研發流程瑣碎問題,從而解放移動研發生產力。
在CI平臺保證集成正確性的狀況下,咱們經過依賴扁平化以及優化集成方式等措施來提高MCI的構建速度,進一步提高研發效率。
咱們創建一套完整自研的靜態檢查體系,針對移動項目的特色,MCI上線全方位的靜態檢查來促進App質量的提高。
咱們對MCI體系的完整流程進行日誌落地,方便問題的追溯與排查,同時經過數據分析來進一步優化MCI的流程以及監控移動App項目的健康情況。
最後,爲了方便管理接入MCI的移動項目,咱們建設了統一的項目信息管理配置平臺。
接下來,咱們將依次詳細探討MCI架構體系是如何一步步創建,進而解決咱們面臨的各類問題。
咱們對目前業內流行的CI系統,如:Travis CI、 CircleCI、Jenkins、Gitlab CI調研後,針對移動項目的特色,綜合考慮代碼安全性、可擴展性及頁面可操做性,最終選擇基於Gitlab CI搭建移動持續集成平臺,固然咱們也使用Jenkins作一些輔助性的工做。MCI體系的CI核心架構以下圖所示:
名詞解釋:
該架構的優點是可擴展性強、可定製、支持併發。首先CI服務器能夠任意擴展,除了專用的服務器能夠做爲CI服務器,普通我的PC機也能夠做爲CI服務器(缺點是性能比服務器差,任務執行時間較長);其次每一個集成任務的Pipeline是支持可定製的,託管在MCI的集成項目能夠根據自身需求定製與之匹配的Pipeline;最後,每一個集成項目的任務執行是可併發的,所以各業務線間能夠互不干擾的進行組件代碼集成。
一次完整的組件集成流程包含兩個階段:組件庫發版和向目標App工程集成。以下圖所示:
第一階段,在平常功能開發完畢後,研發提PR到指定分支,在對代碼進行Review、組件庫編譯及靜態檢查無誤後,自動發版進入組件池中。全部進入組件池中的組件都可以在不一樣App項目中複用。
第二階段,研發根據須要將組件合入指定App工程。組件A自己的正確性已經在第一階段的組件庫發版中驗證,第二階段是檢查組件A的改變是否對目標App中原有依賴它的其它組件形成影響。因此首先須要分析組件A被目標App中哪些組件所依賴,目標App工程按照各自的准入標準,對合入的組件庫進行編譯和靜態分析,待檢查無誤後,最終合入發佈分支。
經過組件發版和集成兩階段的CI流程,組件將被正確集成到目標項目中。而對於存在問題的組件則會阻擋在項目以外,所以不會影響其它業務的正常開發和發版集成,各業務研發流程獨立可控。
組件的發版和集成可否經過CI檢查,取決於組件當前的依賴以及組件自己是否與目標項目兼容。移動研發須要對組件當前依賴有足夠的瞭解才能順利完成發版集成,爲了減少組件依賴管理的複雜度,咱們設計了合理的發版集成策略來幫助移動研發走出繁瑣的版本依賴管理的困境。
每一個組件都有本身的依賴項,不一樣組件可能會依賴同一個組件,組件向目標項目集成過程當中會面臨以下一些問題:
頻繁的版本集成衝突會致使業務協同開發集成效率低下,App測試包的不穩定性會給研發追蹤問題帶來極大的困擾。問題的根源在於目標項目使用每一個組件的依賴項來進行集成。所以咱們經過在集成項目中顯示指定組件版本號以及禁止動態依賴的方式,保證了App測試包的穩定性和可靠性,同時也解決了組件版本集成衝突問題。
組件向組件池發版也同樣會涉及依賴項的管理,簡單粗暴的方法是指定全部依賴項的版本號,這樣作的好處是直觀明瞭,但研發須要對不一樣版本依賴項的功能有足夠的瞭解。正如組件集成策略中所述,集成項目中每一個組件的版本都是顯示指定而且惟一肯定的,組件中指定依賴項的版本號在集成項目中並不起做用。因此咱們在組件發版時採用自動依賴組件池中最新版本的方式。這樣設計的好處在於:
當基礎組件庫的接口和設計發生較大變化時,能夠強有力的推進業務層組件作相應適配,保證了在高度解耦的項目架構下保持高度的敏捷性。但這種能力不能濫用,須要根據業務迭代週期合理安排,並作好提早通知動員工做。
研發流程瑣碎的主要緣由是研發須要人工參與持續集成中每一步過程,一旦咱們把移動研發從持續集成過程當中解放出來,天然就能提升研發生產力。咱們經過項目集成發佈流程自動化以及優化測試包分發來優化MCI流程。
研發流程中的組件發版、組件集成與App打包都是持續集成中的標準化流程,咱們經過流程託管工具來完成這幾個步驟的自動銜接,研發同窗只需關注代碼開發與Bug修復。
流程託管工具實現方案以下:
不管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提供以下功能:
將來MCI 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已經上線了覆蓋代碼基本規範、非空特性、多線程最佳實踐、資源合法性、啓動流程管控、動態行爲管控等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。