淘寶客戶端安全生產體系建設

語言: CN / TW / HK

作者:秦靜超(非臺)

 本文主要講述了淘寶客戶端的安全生產,即在阿里內外成熟的技術方案的基礎上,淘寶客戶端是如何來建設自身的安全生產體系,從研發、構建、釋出、應急四個階段再次推動效率和使用者體驗不斷得到升級。

安全生產

首先我們將“客戶端安全生產”定義為:為預防客戶端研發生命週期過程中發生體驗相關的事故,而採取的一系列措施和活動。

為此淘寶客戶端建立了“‘研發、構建、釋出、應急’一整套規範化流程及平臺”。

圖1 安全生產架構圖

淘寶客戶端安全生產,主要分四個階段:研發期、構建期、釋出期和應急態,同時沉澱開發過程資料,圍繞資料線上線下異常覆盤,為提升程式碼質量、提升開發能力,進一步完善平臺做資料支援,從而提升開發的良好研發環境,保障線上使用者使用體驗。

  • 研發期:這一階段主要是指開發同學把需求開發的階段,往往是單模組的開發,這一階段主要關注模組自身的質量,這一階段安全生產平臺主要通過需求管理、程式碼分支管理、單測管理、Code Review、測試請求|審批,一站式的方式為開發同學提供便利;
  • 構建期:這一階段主要是指開發同學把已經通過測試的程式碼,將程式碼提交到整合區做程式碼的整合測試,這一階段安全生產平臺主要通過質量卡口、包大小分析、產物校驗來確保整合進來的模組是否滿足整合標準(重複的資原始檔、程式碼等或高危的隱私API、除錯程式碼等或不合理的元件匯出、DEBUG程式碼等),通過前置風險分析,防止風險程式碼整合;
  • 釋出期:這一階段主要在通過測試後釋出(灰度、正式)完整的APP、配置變更、活動上線下線,這一階段需關注APP穩定性資料、效能資料、業務資料與輿情資料(端到雲的監控方案),確保釋出的APP滿足使用者的體驗要求;
  • 應急態:前三個階段主要是規避線上風險線,這一階段則是在線上APP無法滿足使用者正常使用時所進入的狀態,線上核心指標波動,會觸發及時告警,從而通過釘釘快速組建應急小隊,對線上問題進行處理,分析問題及問題背後的原因,快速給出解決方案,通過預案回滾、降級處理等手段快速化解線上風險,從而避免風險升級,防止故障產生。

另外為了確保線上APP的高可用體驗,淘寶端架構專門成立了“端側日常保障”小組,主要從事版本值班、大促保障、應急處理、覆盤優化等工作,從日常工作中不斷的發現問題、總結思考、優化流程、改進研發環境,不斷把部分需要人工介入的流程自動化、資料化、平臺化,從而提高“研發、構建、釋出、應急”階段的研發體驗和研發效率,最終把人力從重複的、低效的工作中釋放出來,通過過程資料不斷優化安全生產平臺體驗,從而保障上層業務健康持續發展。讓開發有更多的時間和精力從事更高維度的研發工程,提升開發的成就感。

研發期

研發期主要是開發同學開發為主,這裡平臺提供了程式碼覆蓋率(單測),核心模組中介軟體的單測程式碼覆蓋率需要滿足80%及以上,核心變更需要雙人CR(含TL),非核心變更需要技術專家及以上CR。

構建期

質量卡口

隨著淘寶業務不斷擴張,線上問題時有發生,淘系的場景非常豐富,本地的測試、Review、Monkey、甚至灰度等手段都不能覆蓋到所有的場景。但問題一旦到了線上,所花費的成本都急劇增加。

經過對歷史線上問題進行一些分析,發現其中的相當一部分問題,可以通過 “靜態程式碼分析”, “二進位制產物分析” 等方法提前發現,那麼為什麼不能用技術的手段來提前發現問題,阻斷它們溜到線上呢。例如:

  1. 同名 Category 方法衝突問題, 導致手淘很多功能異常;
  2. @{} 初始化沒判空問題;
  3. oc block持有 c++ this指標導致 User After Free 問題;
  4. objc_msgSend 傳送 alloc 導致記憶體洩露問題;
  5. 一些系統api不再安全,比如vm_remap;
  6. 元件匯出;
  7. 執行緒洩漏;
  8. ......

這些問題上線後可能就引起很難定位的問題,但是在程式碼階段,通過靜態分析等手段就可以阻斷他們的發生。因此客戶端質量卡口平臺應運而生,將手淘客戶端已有問題掃描工具和規則整合,結合DevSecOps卡口設計的開放卡口接入平臺,形成完整的客戶端線下問題發現、治理推動和整合卡口的能力,減少線上問題。

技術方案上,在Android Lint+Spotbugs+Clang Static Analyzer(Android),OCLint(iOS)+Clang Static Analyzer基礎上結合淘系具體平臺和具體問題進行改進,以滿足淘系的技術需求(如掃描執行緒原生介面使用,輔助淘系整體執行緒架構遷移)。

包大小

包大小是客戶端的非常重要的效能指標。從使用者視角看,同樣的功能和服務,使用者傾向於選擇安裝包比較小的App,可以讓使用者用更少的流量下載和更新,一定程度提高使用者的下載率和更新升級率,對於推廣和新增都會有較為重要的影響;從技術視角看,安裝包中的每個檔案都在瘦身的範圍,對不同的檔案型別,需要有針對性的瘦身方案,所以瘦身是一個大工程,包含了很多方面的技術。

Android採用了圖片壓縮(TinyPng,Webp),重複資源合併、shrinkResource 嚴格模式、分包、Proguard、ARSC瘦身、下無用程式碼(程式碼插樁分析)、無用業務下線、遠端so、檢測so除錯資訊。

iOS採用了圖片壓縮(TinyPng,Webp)、編譯優化(不匯出符號、oz、lto)、selectorRef無用資源下線,剔除重複程式碼、業務下線、共享動態庫技術(<iOS9)、Ld連結器壓縮。

產物校驗

產物校驗發生在APP釋出前的最後一個環節,主要來分析本次釋出與上一次釋出核心變更存在哪些具體的差異,來確保本次釋出的正確性。這一環節主要進行了核心程式碼變更分析(啟動、CrashSDK、監控SDK),需要關注核心程式碼變更帶來的可能的風險;元件匯出分析,防止不必要的元件匯出,受到外部攻擊;簽名校驗,防止簽名出錯導致APP無法正常上架;等等。

釋出期

監控告警

淘系高度重視手機使用者的穩定性和效能,通過高可用的度量指標的建立,穩定性和效能的治理,自動化和資料平臺的建設,開發了一套系統化的解決方案及平臺EMAS-MOTU,全方位的提升手機淘寶穩定性和效能。

變更管控

淘系是一個高頻活動運營APP集,我們發現有一些故障是由變更導致的(含活動上線,配置上線等),具有強相關性。因此淘系沉澱了變更管控平臺,變更管控平臺主要作用是監控分析平臺發現的異常資料(Crash、ANR、卡斷、洩漏等)與變更的相關性。

變更管控平臺的核心思路是為每一次變更產生一個唯一的變更ID,並在本次變更下發的過程中,將變更ID加入到監控資訊的變更ID集裡,當監控資訊上報時會帶上所有的變更ID,服務可以對變更ID進行聚類分析,通過相關性確認相同聚類問題是由哪些變更ID產生的,並對具體的變更留觀或回滾,防止風險升級。

通過精確的變更相關灰度染色資料,管控相關灰度和全量釋出,及時卡住異常釋出,避免釋出引起故障,同時也是提高發布效率的核心手段。

應急態

定位

追蹤、度量、日誌

隨著客戶端功能不斷細化與完善,模組化、跨團隊的協同開發方式已經成為了客戶端開發標準的開發方式,模組化、跨團隊的協同開發方式的誕生極大提升了客戶端交付與部署的效率,但同時可以看到這種模組化、跨團隊的架構背後,原先運維與診斷的需求也變得越來越複雜。為了適應客戶端日益增長的功能需求,需實現面向使用者視角的標準化的DevSecOps診斷與分析系統,包括追蹤(Tracing),度量(Metrics),日誌(Logging)。

  • Tracing :用於記錄客戶端行為範圍內的資訊,它在單次請求的範圍內,處理資訊。任何的資料、元資料資訊都被繫結到系統中的單個事務上。例如,使用者進入頁面,到資料渲染的過程。它是我們排查客戶端問題的利器;
  • Metrics :用於記錄可聚合的資料。他們具有原子性,每個都是一個邏輯計量單元,或者一個時間段內的柱狀圖。例如:佇列的當前深度可以被定義為一個計量單元,在寫入或讀取時被更新統計;輸入HTTP請求的數量可以被定義為一個計數器,用於簡單累加;請求的執行時間可以被定義為一個柱狀圖,在指定時間片上更新和統計彙總。例如,從客戶端發起的網路請求數,與正確收到網路資料的接受。它是我們衡量業務巨集觀質量的利器;
  • Logging :用於記錄離散的事件。例如,應用程式的除錯資訊或錯誤資訊。它是我們診斷問題的依據。

基於追蹤(Tracing),度量(Metrics),日誌(Logging)的設計原則,淘系借鑑了OpenTracing實現了全日誌平臺TLog。通過漏斗模型、對比模型通過資料橫向對比可以快速發現自身的效能瓶頸,縮小範圍,提升排查效率。

全景定位

淘系是一個高頻活動運營APP集,我們發現一些故障是由變更導致的(含活動上線,配置上線等),具有強相關性。因此淘系沉澱了全景定位平臺,全景定位平臺主要作用是監控分析線上的變更。全景定位平臺的核心思路是當線上風險產生時,全景定位平臺會主動去收集線上變更,並按時間維度呈現出來,開發可基於全景定位平臺快速檢視線上變更,定位和排查線上風險與變更的相關性,對潛在風險的變更留觀或回滾,直至風險消除。

全景定位與變更管控有一定的相似性,都是對線上變更的監控與分析,區別在於全景定位主要在風險發生後對變更進行分析(業務在變化,無法保障所有的變更都會接入變更管控),變更管控則主要風險發生前打標,風險發生後對變更進行分析,因此全景定位是變更管控的一種補充與保障。

恢復

“對程式碼功能不符合專案預期或程式碼不夠健壯導致App執行時崩潰或異常的線上問題進行恢復”。恢復是淘系應對線上突發問題的重要手段,淘系目前對線上不同的場景採用了不同的恢復策略,目前主要恢復策略有降級、預案、安全模式。

降級

在淘系複雜生態的環境下,大促期間還是會出現由於各種重資源的業務疊加,導致卡頓,體驗明顯下降,記憶體水位暴漲,崩潰率也會隨之飆升。因此從2018年開始,嘗試開始對重資源、高風險業務,針對不同裝置的效能情況進行多維度降級。目的是對使用者體驗進行分級,實現 “高階裝置最炫體驗,低端裝置流暢優先,緊急問題快速降級” (隨著時間的推移,老的裝置的軟硬體條件,已經無法滿足所有新技術、新業務的落地,需要有一定的取捨,從而給每一個裝置最佳的使用者體驗)

針對不同裝置的軟硬體不同特性,基於Listwise-SmartScorer模型,淘系對客戶端設定了高、中、底三個維度,0-100(0表示裝置效能優於市場上主流的0%的裝置,100表示裝置效能優於市場上主流的100%的裝置)的動態的裝置評分演算法。

裝置評分是個什麼? 從機器學習的角度來看:它可能是一個分類問題,即裝置分為高/中/低三類,我們需要區分這幾個類;它可能是一個迴歸問題,即裝置存在一個絕對的分,我們需要去擬合這個分。無論分類還是迴歸問題,都把裝置評分定義為一個絕對的值,而在實際體驗中,我們往往說“iPhone X”比“iPhone 8”快,而不是說“iPhone X” 90分,“iPhone 8” 70分,即裝置評分是相對的,同時由於裝置的損耗,它的評分也是動態的,基於此,我們把裝置評分定義為一個排序問題。

在裝置評分的基礎上,實現統一降級平臺,業務可以通過“高、中、底”或“0-100”選取相應的裝置投放自身業務。

預案

什麼是預案?根據評估分析或經驗,對潛在的或可能發生的突發事件的類別和影響程度而事先制定的應急處置方案。預案可以降低可預估或不可預估的風險,減少損失,而當下面臨大多數的風險,都來自於各類變更,還有阿里最重要的大促場景下,大流量所帶來的系統、業務壓力。預案有分提前預案和應急預案。

提前預案:也稱定時預案,提前預估大促期間的系統狀況與業務狀況,為了避免大促的業務峰值影響而進行的快取預熱、機器重啟、有限降級、磁碟清理或者業務下線等等,一般對業務無影響或影響可控。

應急預案: 針對可能存在的應急情況,如超出預期的異常流量、系統依賴超時及不可用、本系統的非預期不可用等採取的應急手段,一般對業務有損,同時可能會帶來客訴,資損等,需要對應的技術、業務等兜底,執行需要慎重。在新增變更中,在Code Review環節,對程式碼有 “可灰度、可監控、可回滾” (穩定性三板斧)要求,即確保程式碼有應急預案,在線上程式碼出現風險時,快速回滾。

預案和降級的區別在於,預案對全部裝置採取相同的策略,而降級是對不同的裝置採用不同的策略。

安全模式

恢復場景,(啟動階段)未正常使用網路的崩潰問題。網路未初始化導致配置無法下載發揮作用,於是淘系開發了一個安全模式(在連續觸發相同Crash後強制進入“安全模式”--Android輕量級子程序,iOS進入安全模式程式碼,用來在對程式恢復初始狀態(清除歷史產生的持久化資訊),如有必要會觸發配置的下載),為主程序正常啟動做必要的保障。如:啟動時候因為持久化資料出錯,導致APP啟動連續閃退,這時安全模式可以發揮巨大作用,彌補配置下發執行前的程式碼盲區,避免使用者只能通過解除安裝重灌APP才能解決問題。

總結

客戶端安全生產是在淘系較為完善的底層基礎設施上建立起來的規範化、自動化、資料化的平臺。文中涉及到的技術點是借鑑了阿里內外眾多開發、產品、運維等從業人員對歷史問題的總結與實現,這裡感謝參與安全生產小夥伴的努力與付出,同時也感謝阿里以外的開發、產品、運維對豐富客戶端技術、改進使用者體驗的努力與付出。文中更多的是對APP不同階段的問題的思考與解問題的思路,希望對大家有幫助。

參考

[1] 移動研發平臺EMAS:https://www.aliyun.com/product/emas

[2] OpenTracing:https://github.com/opentracing

[3] 安全模式:天貓 App 啟動保護實踐:https://juejin.cn/post/6844903437948157959

關注【阿里巴巴移動技術】官方公眾號,每週 3 篇移動技術實踐&乾貨給你思考!