標籤:

從零打造攜程無線持續交付平台 MCD 實踐

目前攜程大部分訂單已來自移動端,App 幾乎承載了整個集團的所有業務形態。在內部研發中,攜程的 App 已經發展成為擁有 90+ Native Bundle、100+ Hybrid Bundle、30+ React Native Bundle,幾百名研發人員,每個版本(1 個月)交付 4000+個 App 包,Hybrid/ReactNative/HotFix/Bundle 發布次數 500+。

如果沒有一個有效的無線持續交付平台,很難實現大版本的集成發布在 3 天內完成。而對比市場上開源的無線持續集成工具 Fastlane、TestFlight、Jenkins 都存在各種定製化需求的問題。因此我們從零開始,逐步打造適合攜程研發流程的無線交付平台,系統化地解決研發支撐痛點。

下面將從集成、測試、發布、運營四個子平台來展開,具體分享我們是如何一步步打造無線持續交付平台的。

一、集成平台

從最初到現在,攜程無線持續交付模型經歷了從 1.0 到 2.0 的迭代演進。

在 1.0 之前,App 集成和發布還主要依靠人工操作 Jenkins,需要由特定的打包人員負責打包,再將包通過 IM/郵件等方式傳遞給其他測試人員,測試結果需要專人手工回收,以把控 App 質量。此時最大的問題就是 App 管理混亂,人工介入過多,每次發布都需要花費很長的時間。

1、1.0 階段

在 1.0 階段,我們引入 MCD(MobileContinues Delivery)平台思路,將打包人員的工作交給平台來完成,提高了發布工作效率。這時不需要專職人員負責出包,平台會定時自動打包,測試人員可以到平台上自由取包(通過下載鏈接或掃描二維碼的方式)進行測試。

與此同時,測試人員也可以在平台上進行單獨的打包和測試。測試結果會統一反饋到平台上來,協調人員在平台根據各家的反饋結果決定需要重新出包還是繼續下一步發布操作。

在這個階段,App 的打包還完全依賴於源代碼進行,由平台生成打包參數(主要包含 App 運行環境、與 iOS 簽名相關的參數以及代碼倉庫相關的參數)提交給後台的打包系統。它會根據倉庫地址和commit ID 從代碼倉庫中拉取全量代碼,然後打包系統再調用代碼中預先準備好的 Build 腳本構建 App 產物,構建完成後將結果保存至臨時的文件服務中,最後由平台的回收進程將構建結果回收並處理之後放在雲存儲上供用戶下載使用。

2、2.0 階段

1.0 階段雖然已經基本實現了集成打包的自動化,但是還存在以下幾點不足:

  • 源碼打包方式效率低下,每次都要從代碼倉庫中下載全量代碼,再通過源代碼生成 App 產物。這樣做使得每次 Build 時間都很長,而打包次數的增加會導致某些打包任務積壓,系統不能及時出包。
  • 編譯容易失敗,任何一個 Check-in 導致的編譯失敗,就會致使系統不能正常出包。
  • 系統之間採用輪詢模式,Job 任務擴展性差。

MCD 系統發起 Build 請求之後會有另一個定時的 Job 任務去輪詢 Build Server 查看 Build 結果。在初期階段還能滿足業務需求,但是後來由於打包數量的增加以及打包頻率的提高,系統的處理效率變得越來越低。

一方面打包資源不夠(Android 打包使用 Linux 虛擬機,iOS 打包使用 Mac),另一方面輪詢Job 的處理效率達到了瓶頸。打包機器採用 Jenkins 方式進行管理,因此很容易進行橫向擴展,但是 Job 卻很難擴容。

針對以上問題,我們對平台進行了升級改造,主要為:

  • 引入消息機制,提高系統吞吐量;
  • 將工程進行拆分,按照 Bundle 的方式進行打包。

消息機制的改造:

首先基本打包架構和流程保持不變,在 MCD 系統和 Build Server 之間增加消息系統,MCD 發起 Build 之後不再輪詢Build Server,而是消費由 Build Server 產生的 Build 完成消息,如圖 1 所示。使用這樣的生產消費模型 MCD 可以輕易地進行水平擴展,系統執行效率得到極大改善。

圖 1 Bundle 打包

工程拆分:

App 工程拆分成多個不同的 Bundle 模塊,Bundle 之間存在依賴關係。在這個情況下 App 的編譯和打包也可以按照 Bundle 的方式進行組織。

在開發階段,開發人員提交完代碼之後就能直接將自己負責的 Bundle 編譯成可執行文件,測試可以自由選擇 Bundle 進行打包。此時打包工作只需將多個 Bundle 文件組裝在一起就行,極大地加快了打包速度。通過測試的 Bundle 會被發布到指定地點,在 App 集成階段只需把所有發布的 Bundle 組裝成最終 App 供大家測試即可。

在開發自測階段,開發人員提交完代碼後在 MCD 平台上 Build 出所開發的Bundle(標記為 L,表示 Latest)。相關測試人員(或開發人員自己)可以打測試包,測試包會使用所有 Bunde 的 L 版本進行構建。構建完成之後獲取測試包進行功能測試,測試通過後就可以將該 Bundle 進行發布操作,即標記為 RC 版本(表示 Release Candidate)。

圖 2 測試打包發布

如圖 2 所示,在集成測試階段,MCD 平台會自動選取已發布(RC 版本)的 Bundle 打出集成包,測試完成後測試人員可以將測試結果反饋到 MCD 平台中,待測試全部通過之後就可以安排 App 進入發布定版階段,再進行一些後續市場包操作就可提交給 App 應用市場供用戶下載。

由於 App 的開發是個連續過程,測試包和集成包都可以很方便地配置是需要 Hourlybuild 還是 Daily build,並且可以和測試平台的相關功能聯動,從而實現持續集成。

我們也會將不同版本(不同功能)的 App 按照項目進行劃分,主版 App 為標準項目,非主版(渠道/HotFix/Bundle)App 為非標準項目,同一項目內的 Bundle 可以自由組合,項目之間互相獨立,不受影響。一個項目在創建時可以選擇從另一個項目繼承其各模塊的最新版和發布版。項目在開發過程中也可以從其父項目中實時同步對應模塊的最新版和發布版,這樣就能基本滿足各種開發和測試的需求。

二、測試平台

隨著攜程持續交付的發展,原有的測試模式以及流程漸漸顯現出不足,主要體現在以下三點:

  • 快速驗證與手工驗證的衝突;
  • 自動化回歸測試與手動測試效率的矛盾;
  • 設備兼容測試與設備不足的矛盾。

1、快速驗證與白屏檢測

在集成測試階段,每一次出包首先會由基礎測試人員負責驗證此次出包的質量,主要是驗證各個 BU 入口頁面 Hybrid 或直連頁面是否正常,如果大量 BU 入口頁面異常則會要求重新出包。這個過程看似很簡單,但是「(溝通成本+驗證成本)*出包次數」所耗費的時間也是不容忽視的,且這種冒煙測試對於測試人員也很枯燥無趣。

圖 3 集成包

針對以上情況,最初引入了白屏測試等基礎性測試功能,並與集成平台打通(見圖 3,可以直接從集成包列表選擇相關測試功能)。

白屏測試主要是檢測 App 首頁各個入口頁面是否顯示正常,對於每一個頁面會進行圖像比對以及頁面長度來驗證頁面是否正常,白屏會在多個設備進行測試,只要其中一台設備通過,則認為這個入口是正常的。

2、自動化回歸測試

通過回歸測試自動化,可以提高回歸測試效率,有效緩解測試人員的壓力。我們逐步開發了 MCD 測試平台用於自動化測試項目的管理、執行、報告和展示,支持Android/iOS App、HTML5/Hybrid Testing。

圖 4 測試平台架構

測試平台架構簡化圖如圖 4 所示,各個模塊主要功能如下:

  • Portal 負責與用戶交互,查看報表,保持後台系統對用戶透明;
  • Invoker 是調度通道,用戶基於 Portal 提交的測試任務通過此通道來調度,包括創建項目、設備佔用、測試項目執行等;
  • Lab Center 負責所有與設備相關的業務,Lab Center 與二次開發的開源軟體 STF 交互,所有設備掛載在 STF 上;
  • 當具體的測試項目在 Jenkins 上執行時,會將預先佔用的設備遠程連接到 Slave 上等待使用。

MCD 測試平台提供了自動化測試(白屏檢測、錄製回放、回歸測試)、系統測試(兼容性、性能、穩定性)、手動測試(遠程租用、遠程調試)三大類功能,基本達到了我們對於提高測試效率的需求,如圖 5、圖 6 所示。

圖 5 Mobile 項目列表

圖 6 自動化測試 Task Case 頁面

另外,日常測試中還經常遇到這些情況:需要快速驗證 App 的一個功能,有些問題只能在特定機型上重現,測試目前卻沒有這款手機。因此我們基於STF 二次開發出設備共享平台,將空閑設備收集起來在平台上共享,用戶只需在平台上搜索需要的設備就可以立刻通過STF 進行使用了,如圖 7 所示。

圖 7 設備租用

同時,我們還建立了代碼質量的自動化,集成 Sonar、Facebook Infer 和 Uint Test 功能,方便每個版本對代碼質量進行跟蹤,如圖 8 所示。

圖 8 代碼質量自動化追蹤

三、發布平台

無線發布系統一直以來都是無線應用能快速迭代最關鍵的一環,一個好的發布系統能幫助開發快速地修複線上問題,並能快速將新功能投送至用戶,幫助業務搶佔市場,而發布系統的設計也隨著 CD(Continuous Delivery)概念的深入人心而日新月異。

無線發布的特點是靜態資源包(不管是 Hybrid、React Native 還是 HotFix、Bundle),發布技術中涉及到的主要問題如下:

  • 如何最大限度地把靜態資源的下載流量降到最低,以減少用戶對應用更新的感知度,提高應用升級的成功率和用戶體驗。
  • 灰度發布,保證發布的質量。

1、資源包發布

針對靜態資源包發布,經歷了如下幾個歷程:

  • 全量包發布: 攜程最初使用的都是全量發布的方式,這種方式實現簡單,但也簡單暴力,而問題也比較明顯,導致用戶升級時流量巨大。
  • 文件字元串差分: 這種方法避免了整包差分的問題,能夠比較方便地實現快速迭代要求下的小量更新需求,並且文本差分工具簡單,實現容易,出錯較少,但缺點是差分效果差。
  • 文件二進位差分: 對每個文件進行二進位級別的差分能夠具備小量快跑的特點,同時進一步優化差分文件 Size。這也是攜程目前使用的方式,它仍然使用了 bsdiff 作為差分工具,當文件沒有更新時,不輸出差分文件,而更新時也只產生 Size 非常小的 diff 文件。
  • 按需差分: 在按需差分前,我們採取的是預差分方案。就是在發布時,把所有的版本間差分準備好,有多少個歷史版本就將產生多少個差分包。按照這種做法,隨著發布次數的增多,發布差分包數量也將急劇增長,對存儲的要求越來越高,也造成了浪費。

在此前提下,引入了按需差分,就是終端用戶通過將自己的版本號與線上最新版本號做比較,發現落後時,觸發差分過程,從而獲取增量更新。

這裡會有一個問題——終端用戶第一次訪問時沒有差分包,我們的做法是:第一次只返回全量包,用戶不用等待,但是後續用戶會拿到差分包。

另外一個問題是,避免重複打差分包。在計算時發現無差分包,會觸發差分包過程,同時會把這個信息緩存(過期時間半個小時)。當其他客戶端同樣的版本請求時,會先判斷緩存,沒有的話進行差分操作,有的話直接下發全量包。

2、灰度發布

網站發布通常是有灰度發布的過程,無線的發布跟網站發布流程是類似的,但是做法有差別。二者的區別是:網站是 centralize 的,可以統一控制,而無線的發布是 decentralized。無線發布包,像 Hybrid、React Native、HotFix 等靜態資源,是需要客戶端一個個來拉取的。那麼,如何確保整個發布的流暢,確保發布質量呢?我們的解決方案如下:

Offline 灰度發布流程

灰度第一步是冒煙,網站的冒煙是導一部分流量到某台 Server 上,而我們則是通過配置一個白名單,只有客戶端在白名單中的才會獲取到最新發布。當測試沒有通過,可以選擇終止,然後再決定是否需要回滾,測試通過決定是否需要擴大比例。

監控發布數據

當客戶端收到下載物後,會把當前的下載信息上報上來,供發布人員進行監控查看。

灰度發布設計中需要注意:

  • 避免一直小白鼠:為了避免一個用戶一直當小白鼠,每次灰度需要利用灰度 ID+客戶端信息進行取模運算。
  • 灰度回滾:灰度回滾時只需要回滾已經更新這次灰度的客戶端,對於沒有更新到的,則無需回滾。

四、運營平台

運營是研發流程的最後一環,攜程的 MCD 平台思路是能夠針對發布結果、運營情況以及配置等功能有一個集中的管理。目前包含了運營看板、性能看板、發布看板、無線配置、崩潰管理、App Size 統計等模塊。

其中無線配置經歷了多次迭代,對於各種配置項,從版本、平台、渠道、A/B 多個角度進行了定義,做到靈活動態配置,需改就改,粒度大小自由配置。下發時根據App 的版本、平台、渠道等信息挑選符合條件的配置進行發布。需要修改的時候也是先修改測試環境配置,測試通過後再同步到生產。配置分為專用版和通用版兩種,專用版只會下發給特定的渠道/版本,通用版以版本號為基準,在不發布新版本配置的情況下系統默認給 App 端下發最近的通用版配置。當同時存在符合條件的專用版和通用版的時候,只下發專用版配置。

崩潰管理也是無線運營的重要一環,儘管目前行業內已經有崩潰管理功能強大的平台,但由於定製性需求我們也搭建了自有崩潰管理功能,方便快速發現線上問題,從而能夠通過 HotFix/Bundle 方式及時修復,如圖 9 所示。

圖 9 崩潰管理頁面

五、結束語

以上是攜程無線基礎工程團隊在無線持續交付方面的一些工程實踐,MCD 的核心目標是能夠對集成、測試、發布和運營的完整生命周期提供更好的平台支撐和管理。雖然取得了一些成果,但還有許多提升空間,例如多應用支持、支持條件發布等,無線持續發布之路依然有很多工作要做。

【作者簡介】劉李豐,攜程無線基礎工程團隊高級經理,負責無線交付平台和基礎服務研發。十多年的互聯網從業經驗,曾供職於 eBay 等互聯網公司,研發經驗豐富。

沒看夠?更多來自攜程技術人的一手乾貨,歡迎搜索關注「攜程技術中心」微信公號哦~

推薦閱讀:

如何看待攜程收購藝龍 37.6%股份成為最大股東,未來的國內OTA會怎樣發展?
「去哪兒決定自己建一家航空公司」背後意味著什麼?
買機票,Qunar 上搜索到的機票為什麼比攜程便宜?
攜程網為什麼要控股「蟬遊記」,看中它什麼?
極光之旅:阿里旅行的邊緣戰略

TAG:携程 |