餓了麼移動基礎設施建設

軟件 餓了麼 iOS 工程師 CSDN 2017-04-05

引言

自 iOS 及 Android 操作系統面世以來,移動端的浪潮以極快的速度席捲了整個世界。而在這樣的時代演進過程中,技術的不斷進步和創新給移動端的開發者們帶來了一次又一次的挑戰,比如不斷增長的日活用戶、不斷刷新的版本分佈、不斷碎片化的機型分佈以及不斷碎片化的操作系統分佈等。其中,隨著日活用戶的不斷增長,微小概率的閃退使越來越多的用戶在體驗上大打折扣。同時, App 版本分佈的不斷增加亦加劇了代碼的碎片化,致使功能管理愈加複雜。

另一方面,手機型號與操作系統版本增多,也給移動端開發者造成了不少困擾。特別是 Android 平臺,由於其開放性,導致了大量專項開發與優化,增加了代碼管控的難度與複雜度,這也給移動開發者提出了更高的挑戰。

面對這一系列技術挑戰,餓了麼開啟了移動基礎設施的建設工程,以應對未來在移動端所面臨的變化以及更多挑戰。本文將從以下幾個方面細談餓了麼移動基礎設施建設的實踐:

  • 移動端用戶體驗的分級;

  • 移動基礎設施的概念;

  • 餓了麼移動基礎設施的建設實踐。

移動端用戶體驗的分級

在這樣一個以用戶體驗為王的時代,追求極致的用戶體驗往往是產品經理們追逐的最高夢想。因此,更簡化的流程、更炫酷的動畫總是成為每次產品更新迭代的主角,從不會褪去其“No.1”的光環。

然而事實上,App 和過去 Web 時代的產品有著分明且本質的區別,比如用戶更新意願低、存在故障時難修復、視覺要求更高等。因此,在這樣一場追求 App 極致體驗的戰爭中,移動端的程序員兄弟們也應該是並肩作戰的團隊成員之一。因為技術上的用戶體驗,重要程度其實並不亞於以上的主角。

Level 1 能用

“能用”是每個用戶對於使用 App 最基本的訴求。但當我們鍾愛的 App 在使用過程中遇到諸如內存訪問越界等特殊異常時,它往往會表現出一種最讓我們反感的現象——閃退,移動端工程師們稱之為“Crash”。

這種讓 App 完全無法使用的情況是用戶最為惱火的場景。因此,如何最大限度地降低 App 的 Crash 率便成為了移動端技術人員們追求的用戶體驗最高核心。一款無法穩定運行的 App 當然無法得到用戶的青睞!

Level 2 可用

“可用”,來自為用戶提供穩定可靠的服務表述,這是比較容易理解的。設想一下,當我們正在選擇美食時,卻提示網絡不可用;又或是頁面上的菊花轉了一分鐘也沒有出現想要的菜單,這些都會讓我們對這樣一款 App 產品失望。然而,“可用”卻又是比較難實現的一個等級。當用戶量少、業務簡單時,網絡的流量並不會對服務器端造成過大壓力;而隨著用戶量的增長,不同地域、運營商、網絡環境的一點點小的抖動,都會導致用戶網絡請求的不確定性。

因此,如何最大限度地保障網絡數據的穩定性,讓我們的 App“可用”,是每天都在面臨的挑戰。

Level 3 好用

當我們的 App 達成了“能用”和“可用”的體驗後,便來到了第三個層次——“好用”。

與前兩者體驗需求的不同之處在於,“好用”除了在產品上要求流程簡單便捷外,同時也對動畫效果提出了更高的要求。在技術上這往往表現為每秒刷新的“FPS”幀率達到一定數值,頁面切換無卡頓感,同時 App 能夠在第一時間響應用戶的觸摸操作等。

“好用”是對產品經理以及應用開發者在頁面性能優化上的極致挑戰,是一個長期追求,並不斷努力的終極目標。

移動基礎設施的概念

在以上的用戶體驗分層概念中,我們可以看到,這種用戶體驗的提升是不斷打怪升級的戰役,自然也少不了坎坷。在很長一段時間內,由於缺乏相應的測試和監控工具,App 端的問題一度只能通過後端監控來推斷。為了更好地應對這樣一系列與 App 相關的問題,我們提出了建設移動基礎設施的構想。本節先來談談什麼是移動基礎設施。

我們都知道,一款 App 的研發流程大致可以總結為:

  • 產品提出設計原型,UED 設計好視覺效果稿;

  • 工程師針對設計稿件進行編碼、Debug,完成開發;

  • 工程師將開發好的程序進行打包、發佈;

  • App 產品正式上線併發布。

而在最近幾年,隨著 iOS 和 Android 的技術進步,又出現了一系列線上熱修復技術,因此在以上的 App 研發流程中再添一員——“HotPatch 修復”。

再簡單一點,可以直接歸納為:產品→開發→發佈→線上→修復。

而移動基礎設施(Mobile Infrastructure,我們稱之為“Minfra”)提供了除產品流程以外的一整套 App 研發管控的 SaaS 服務,即涉及開發、發佈、線上和修復的全生命週期管控平臺。

餓了麼移動基礎設施建設的實踐

餓了麼移動技術團隊在面對以上流程時,搭建了名為“Grand”的總體管控平臺,並分別建立相應的管控模塊來進行保障工作。接下來將分模塊談談每個流程的具體細節。

持續集成

持續集成是每個互聯網公司基本都會部署的一道開胃菜,通過代碼倉庫的“Webhook”操作來自動觸發一次編譯構造,從而快速定位該代碼集成是否會導致整個項目崩潰。這一步,是一項“掌控代碼”的操作。

對於持續集成的平臺搭建來說,業內最常用的便是“Jenkins”。通過簡單的“job”配置就可以輕鬆跑起一款 App 的持續集成。同時它還具備強大的可擴展性、簡便的集群管控能力。也正因為這些優點,我們最終選擇了“Jenkins”。

然而在餓了麼,由於 App 數量眾多,且隨時可能會有新的 App 成員加入。於是乎,在這樣一種業務場景下,為每款 App 都單獨進行一次自定義配置就成了奢望。如何使用一個“job”就能讓所有 App 都跑起來,是我們首要解決的問題。

得益於“Jenkins”平臺的高度可自定義性,我們使用自己的 Python 腳本完成了持續集成的管控工作(如圖 1 所示),同時使用“Grand”平臺實現前端狀態的監控工作。每款 App 使用一個預定義好的配置,來配合腳本內預定義的不同打包行為,最終彙總結果於“Grand”平臺。

持續集成平臺的搭建,讓團隊合作的代碼最終趨於穩定狀態。完全自定義的腳本代碼,讓未來“靜態代碼檢測分析”、“自動化測試平臺”的加入成為可能,真正實現了對代碼的掌控。

圖 1 Jenkins 管控頁面

Release

代碼已經 OK,功能也已完備,接下來就是接受千萬用戶檢驗的時刻了。在此,“發佈”這個看起來最尋常、最微乎其微的功能服務,卻是發揮極大作用的功臣。我們前面提到,由於用戶量巨大,99.99%的 Crash 率也能給成千上萬的用戶帶來困擾。為了最大限度地減少這種困擾,一個具備“灰度發佈”的服務被賦予了非凡的意義。

餓了麼移動基礎設施建設

圖 2 App 發佈灰度配置信息

通過向特定的手機、城市甚至人群發送升級提醒,讓部分、少量的用戶升級至新 App(如圖 2 所示),以觀察這部分用戶的 Crash 率成為了我們防止大規模 Crash 最主要的解決方案之一。在灰度的過程中,一旦發現 Crash 率快速上升,則可通過關閉“發佈”渠道來防止事態的進一步升級,讓“能用”這一用戶體驗等級得到掌控。

看到這裡,一定有讀者會產生疑問,對於 Android 操作系統而言,以上方案或許可行,但對於 iOS 是否有更加可行的方案?

的確如此,對於 iOS 平臺而言,由於 App Store 的存在,往往很難達到灰度控制的目的。事實上,如果有條件的話,可以適當地採用 iOS 企業版來做灰度。不過這種方案並不被推薦,企業版也不是為該種目的而生,所以我們也並未完全採取這種方案。

另一種 iOS 的灰度渠道方案,則是在各大越獄社區進行分發,同樣可以繞過某些監管。當然,由於安全性原因,也具備一定風險。因此,如何取捨還是得看讀者自己衡量。

HotPatch

上文提到,在我們的 App 發佈過程中,一般會讓部分用戶進行升級,通過觀察其 Crash 率來決定是否最終全量該版本。在過去,這部分用戶被“犧牲”後,如果其不主動再次升級自身軟件版本,陰影將永遠籠罩在他們的頭頂。然而數據告訴我們,移動 App 用戶的主動升級率一直處在低位,因此總會有這樣一些用戶不斷被這團陰霾所困擾,最終選擇離開我們。

在這種歷史情景下催生的“HotPatch”技術,簡直就像是救命稻草一樣,拯救了一大批這樣的 App 用戶,同時也拯救了在移動端默默奮鬥的程序員們。只需通過“HotPatch”服務有針對性地下發修復 Bug 的 Patch 包,就能達到降低 Crash 率的目的(如圖 3 所示),從而很好地提升用戶的基本體驗。也就難怪該項技術出現後,各大廠商都趨之若鶩。

餓了麼移動基礎設施建設

圖 3 通過“HotPatch”發佈包

小結

我們通過提供“持續集成”、“Release”以及“HotPatch”三項服務,使用掌控代碼、掌控灰度以及掌控閃退的方式,來避免技術原因所造成的閃退,讓用戶體驗的第一維度——“可用”,這一最基本的訴求得到了滿足。

對於用戶體驗的第二維度,在去年一個很火的詞——“APM”,讓其成為了可能。

APM

在用戶體驗第二維度的世界裡,網絡問題是最主要的問題。事實上,網絡問題歸根到底也基本就是兩個問題——網絡延遲與網絡錯誤。

在沒有移動 APM 基礎設施之前,遇上網絡問題時,基本只能求助於後端的監控系統。但當用戶的請求並未到達我們自身的 IDC 機房時,比如因運營商劫持、某省網絡抖動等產生的延遲和錯誤,大多隻能靠經驗或猜想來解決。這時如果能從 App 端的視角來看待其發生的網絡情況和問題,就能更有針對性地瞭解其產生症狀的根本。

為了達到收集每款 App 所有網絡請求的目的,我們採用了移動端的“AOP”技術,來獲取該 App 中發生的每個網絡請求的時間信息。這些時間主要包括網絡協議棧上的“首包時間”、“DNS 時間”、“TCP 時間”、“SSL 時間”和“請求時間”。當然,我們也同時獲取網絡層的錯誤信息,主要包括 HTTP 層的網絡錯誤碼,以及網絡鏈路層的錯誤代號。

餓了麼移動基礎設施建設

圖 4 服務響應數據一覽

分析以上網絡數據中的各個時間序列,基本能夠了解從用戶設備到機房的各項網絡時間,從而更方便地確認導致用戶網絡請求緩慢的原因是來自於網絡的延遲,還是後端的響應超時。如果後者是主因,還能再通過該請求的唯一標示符去查詢後臺的監控系統,追本溯源,最後有針對性地優化與解決。而通過上面的網絡錯誤碼,可以在第一時間瞭解用戶端大量發生的網絡鏈路問題情況,為服務器端出現的問題提供寶貴的數據支撐(如圖 4 所示)。

通過“APM”的網絡層錯誤的收集,可以實時發現某個域名主機所發生的問題。這時,如果能同時結合該域名主機的響應時間,以及後端的監控系統,便能夠達到整條網絡鏈路監控打通的目的,讓每一次的服務請求都有跡可循有源可溯,真正做到讓我們的 App 能夠持續地“可用”。

俗話說得好,沒有度量就無法提高。網絡監控提供給我們的數據便是提升用戶體驗最好的度量,讓我們能夠持續不斷地提升“可用”服務的質量。

未來

現在,我們的 App“能用”、“可用”,那麼如何更進一步讓它“好用”?這便是我們接下來所追求的最終目標。我們設想,如果能夠實時瞭解 App 用戶在使用過程中的各項流暢度體驗數值,就可以在接下來的版本中有針對性地對相應的功能進行優化;同時,如果能夠了解到我們的用戶在研發實驗室中沒有的機型以及 OS 版本上的各項數值,也就可以幫助我們的研發人員有針對性地對該機型或操作系統進行相應的優化,從而提升用戶的流程度體驗。

另一方面,更好的代碼質量檢查也是“Grand”接下來所需進行的工作之一。且隨著我們移動自動化測試平臺“Stellar”的研發和加入,相信“Grand”會在不久的將來,能夠成為綜合一鍵打包、發佈、自動化監控和告警的智能移動基礎服務平臺。

作者簡介:王朝成,餓了麼移動技術移動基礎架構組負責人、移動架構師,負責餓了麼移動技術的遠景規劃、技術架構選型、外部技術方案評估等工作。目前關注領域包括移動端架構、安全、自動化測試及移動大數據等。

責編:唐小引,技術之路,共同進步。歡迎技術投稿、給文章糾錯,請發送郵件至[email protected]

聲明:本文為《程序員》原創文章,未經允許請勿轉載,更多精彩文章請訂閱2017 年《程序員》。

相關推薦

推薦中...