支付寶移動端動態化方案實踐

小螞蟻說:

此前分享的《模塊化與解耦式開發在螞蟻金服 mPaaS 深度實踐探討》(想要了解更多相關內容,歡迎關注公眾號:mPaaS )已經對支付寶在移動端開發架構的設計思路有了初步瞭解。本文將結合在 iWeb 武漢站的分享,帶領大家進一步瞭解 mPaaS 在移動端動態化方案設計。

分享內容將分為以下三個方面:

  1. 支付寶動態化方案的探索;
  2. Nebula 框架淺析;
  3. mPaaS 科技賦能

支付寶動態化方案的探索

任何一種技術方案都是在業務的發展和架構的演化中逐漸探索出來的,因此我們來看一下支付寶架構的演進:

支付寶移動端動態化方案實踐

支付寶從最開始的工具型應用,逐漸發展成平臺型應用,一直到現在,已經成為了一個超級 App,它擁有多應用的生態,更加開放和動態化,並且保持著高可用,高性能,高靈敏的強大特性。隨著 App 的逐漸龐大,整個應用的架構也在進行不斷的調整,來適應各種特性。現在的支付寶客戶端的架構如圖所示:

支付寶移動端動態化方案實踐

整體架構分為五層:容器層、組件層、框架層、服務層、應用層。

客戶端整體採用統一的框架開發,模塊化的開發模式,完全插件式的容器,支持模塊獨立發佈,方便大規模團隊的並行開發。

在這樣的框架結構中,同樣包括了我們的動態化方案。支付寶中的動態化方案主要有兩種框架:Nebula 和小程序

支付寶移動端動態化方案實踐

這兩種方案不僅解決了需求迭代速度和發版週期之間的矛盾、跨平臺開發、實時發佈等一些普適問題,而且有效地保證了發佈質量,對線上問題進行緊急止血,同時也有助於建立良好的開放生態。

Nebula 是支付寶移動端 Hybrid 解決方案,它提供了良好的外部擴展功能,擁有功能插件化、事件機制、JSApi 定製和 H5App 推送更新管理能力。

支付寶移動端動態化方案實踐

主要功能包括:

  • 接入 H5App 後臺,方便管理離線或者在線 H5App,實現 H5 應用的推送、更新。
  • 加載 H5 頁面,並按照 Session 的概念進行管理各個頁面。
  • Android 使用 UCWebView,擁有解決系統級 Webview Crash 的能力,內存管理更合理,網絡加載提升更快,兼容性更好。徹底告別了在Android下兼容不同 Webview 的問題。
  • 支持自定義網絡庫,自定義網絡通道;支持自定義鍵盤,自定義 Native View替換 H5 標籤。
  • 提供豐富的內置 JSAPI,實現譬如頁面 push、pop,標題設置等功能;支持用戶自定義 JSAPI 和插件功能,擴展業務需求。
  • 自帶埋點功能,接入 H5 監控平臺,能夠實時看到頁面加載的性能、錯誤報警和監控。

還有一種動態化方案就是支付寶小程序:

支付寶移動端動態化方案實踐

支付寶小程序是一種全新的開發模式,融合了 H5 的易開發性、跨平臺性、Native 性能,讓開發者可以快速開發高性能的頁面,提供優異的用戶體驗。通過使用支付寶小程序,開發者為支付寶開發了大量優質的小程序,豐富了支付寶生態能力。小程序開放給開發者更多的 JSAPI 和 OpenAPI 能力,通過小程序可以為用戶提供多樣化便捷服務。

Nebula框架淺析

Nebula 的架構如圖所示,從上至下依次為 H5 應用層、服務層、原生框架層:

支付寶移動端動態化方案實踐


  • H5 應用層:基於 HTML 和 JavaScript 技術開發,在 H5 容器上運行的手機應用,它擁有跨平臺的特性,配合離線包的使用可以完成實時熱修復的功能。
  • 服務層:為開發者提供了高階語言的 API 來使用手機系統資源,包括:
  • 視窗系統,開發者可以使用它來創造應用 UI,包括文字,圖片,按鍵及定製 View
  • 資源管理,通過它開發者可以方便的訪問如多語言文字,圖片和佈局等非代碼資源
  • 應用生命週期管理,它決定應用在手機系統裡的開始,結束以及強制關閉的時機
  • H5 容器
  • 原生框架層:是手機系統的基礎層,它提供了標準 API 來讓高階語言(比如 Java 和 Object-C)使用底層的硬件,幷包含了許多為硬件訪問的專有軟件庫。當上層調用某個框架 API 來訪問硬件時,手機系統將加載相應的軟件庫。

整個 Nebula 框架的核心部分就是 H5 容器,下面看一下 H5 容器的結構:

支付寶移動端動態化方案實踐

在容器裡面有 H5Service、H5Session 和 H5Page 這樣三個概念

H5ServiceH5SessionH5Page 都是從 H5CoreNode 類擴展而來,以 H5Service 為根節點,它與其他類一同形成了樹狀結構構成了頁面流程和導航。在一般情況下,H5Pages 是 H5Session 的子節點,而 H5Sessions 是 H5Service 的子節點,在任何情況下只有一個 H5Service 根節點存在。

  • H5Service:是 Nebula 裡維護 H5 應用全局狀態的基礎類, 在 H5 應用的生命週期內只有一個 H5Service 的單例全局實例,H5Service 可以進行的操作包括:
  • 創建且打開一個新的 Web activity
  • 創建且開啟一個新的 Web page
  • 從共享空間存儲和讀取數據
  • 註冊插件和 Provider
  • 監聽應用的生命週期
  • H5Session:一個 H5Session 是由一疊 H5Pages 組成的完整業務流程。例如一個收銀臺的流程包括:一個購物車的小結頁面,一個結賬方式的選擇頁面,和最後一個結賬確認頁面。所有的頁面都可以獨立存在運作, H5Session 在其中的作用是把這些頁面組織起立,按照業務邏輯把它們按序排列來完成業務。當你使用 H5Service 創建且開啟一個新的 Web page 時,如果當前沒有 H5Session 的話,一個新的 H5Session 實例將被創建,併為後續創建的 Web page 共享。你可以從 H5Session 中移除頁面直到頁面疊為空,也可以使用 H5Session 所提供的方法來獲取首頁,以及監聽該 H5Session 的生命週期。
  • H5Page:是用戶看得見,摸得著的頁面,也是應用生命週期中最重要的一部分。你可以通過 URL 來加載內容,用 H5Param 來定製頁面的外觀和行為,甚至可以通過獲取 H5Page 的視圖層次,把 H5Page 視圖和其他原生 UI 部件一起內嵌到同一個佈局中。

下面是 H5 容器的幾個重要組成部分:

  • API 管理器主要管理 JS API:Nebula 中已經提供許多內置的 JS API 供開發者使用,比如操控 UI,顯示對話框和 Toast,以及使用網絡 RCP 服務等。
  • 插件管理器主要管理 Plugin:如果現有的 JS API 無法滿足你的業務需求,你也可以選擇創造一個新的插件。你只需把原生代碼打包在插件中,在管理器裡註冊該插件,便可在 Javascript 層使用新的 JS API 了
  • JS Bridge 是連接原生層和 Javascript 的溝通橋樑:它將 Javascript 代碼轉譯成能在系統框架運行的字節碼,同時也把原生層的數據結構轉成 Javascript 對象使其能在 Javascript 層處理。這裡 Nebula 針對JS Bridge 做了一些優化:
  • 在 Android 裡,js 調用 native 的通訊是通過 console.log 的方式,這個和其他容器實現不一樣,其他容器一般通過 prompt 的方式來實現的,但是使用 prompt 的方式,有兩個弊端:
  1. 使用 prompt 會阻斷整個瀏覽器的進程,如果 native 處理時間一長,會導致頁面假死。
  2. prompt 是在 UI 層面上會彈出一個模態窗口,在 native 沒有對其進行捕獲處理的話,會造成一個問題。一旦這個頁面放在非此容器的環境下,就會出現一個很詭異的 prompt 彈窗。在支付寶內,曾經出現過這個問題,天貓頁面在支付寶 app 裡的時候,由於容器機制不同,頁面中 bridge 腳本沒有判斷環境,導致頁面中 js 調用 API 的時候,在頁面上出現了 prompt 的模態對話框,嚴重影響了用戶體驗,但是如果使用 console.log 的話,就不會出現這個問題。console 的方式避免了不兼容環境的體驗問題和同時也避免了頁面的假死。
  • jsbridge 注入的時機,由於業務邏輯要依賴 bridge,所以業務的所有邏輯都會在 bridge ready 之後才會觸發,而 bridge js 本身運行是要一定的時間的,因此注入的時機對於性能的影響顯得非常的重要。但由於 H5 頁面的生命週期和容器的生命週期是相互獨立的,因此在 H5 生命週期的哪個階段注入這段 bridgejs,對於性能的影響就顯得異常重要。
  • 現在在支付寶內使用的方式為監聽 H5 生活週期的事件,比如說當 Webview 設置 title 結束之後,Android 會放出一個 onReceivedTitle、shouldInterceptRequest 等事件,iOS 會嘗試在 webViewDidStartLoad 事件,在監聽到這些事件之後,立即注入 bridgejs,讓其在 H5 生命週期儘早運行。通過這種方式的注入,經過測試,最早能在頁面加載開始後, 50ms 以內就能成功注入 bridgejs。
  • Event 機制:Nebula 提供了一套事件機制來管理事件在 H5Page,H5Session 和 H5Service 之間的流通順序。一個 H5Event 可以在 H5Page, H5Session 或 H5Service 任何一層發生,事件派遣分為兩步完成事件攔截。
  • 這個步驟中事件派遣的順序為 H5Service -> H5Session or H5Page
  • 事件可以在任何節點被攔截 (如果 interceptEvent() 返回 true ),也可以在任何節點被處理 (如果 handleEvent() 返回 true ):如果事件在派遣過程中被攔截或處理,該事件將被視為已被消費且不再繼續流通。如果在派遣過程後事件依舊沒有被攔截或處理,會有錯誤拋給呼叫方處理。

僅僅使用傳統的 H5 技術展示在線頁面,很容易受到網絡環境影響,因而降低 H5 頁面的性能。

在 Neblua 中我們使用離線包技術來解決這個問題。離線包是將包括 HTML、Javascript、CSS 等頁面內靜態資源打包到一個壓縮包內,它的目錄結構如圖所示:

支付寶移動端動態化方案實踐

使用離線包可以使容器內的 H5 應用具有接近 Native 的體驗,主要優勢如下::

  • 減少網絡環境對 H5 應用的影響:通過下載離線包到本地,然後在客戶端打開,把打開H5頁面的操作從網絡 IO,變成磁盤 IO。直接從本地加載離線包,不僅最大程度地擺脫網絡環境對 H5 頁面的影響,而且增強了用戶體驗。
  • 提升用戶打開 H5 應用的體驗:通過離線包的方式把頁面內靜態資源嵌入到應用中併發布,當用戶第一次開啟應用的時候,就無需依賴網絡環境下載該資源,而是馬上開始使用該應用。
  • 實現動態更新:在推出新版本或是緊急發佈的時候,您可以把修改的資源放入離線包,通過更新配置讓應用自動下載更新。因此,您無需通過應用商店審核,就能讓用戶及早接收更新。

下面介紹一下離線包的渲染過程當 H5 容器發出資源請求時,其訪問本地資源或線上資源所使用的 URL 是一致的。H5 容器會先截獲該請求,截獲請求後,發生如下情況:

  1. 如果本地有資源可以滿足該請求的話,H5 容器會使用本地資源。
  2. 如果沒有可以滿足請求的本地資源,H5 容器會使用線上資源。因此,無論資源是在本地或者是線上,WebView 都是無感知的。
支付寶移動端動態化方案實踐

離線包的下載依賴用戶當前的網絡。一般情況下,只有在連接 WIFI 的情況下才會在後臺下載離線包。如果用戶處於移動網絡下,不會在後臺下載離線包。如果當前用戶點擊 APP,離線包沒有下載好,用戶就要等待離線包下載好才能用。

為了解決離線包不可用的場景,fallback 技術應運而生。每個離線包發佈的時候,都會同步在 CDN 發佈一個對應的線上版本,目錄結構和離線包結構一致。fallback 地址會隨離線包信息下發到本地。在離線包沒有下載好的場景下,客戶端會攔截頁面請求,轉向對應的 CDN 地址, 實現在線頁面和離線頁面隨時切換。

那麼本地資源如何尋址呢,我們設計了獨特的虛擬域名機制,僅對離線應用有效。當頁面保存在客戶端之後,WebView 如果要訪問的話,是通過 file schema 來從本地加載訪問的。然而,用戶就能在地址欄裡直接看到 file 的路徑,這就會導致以下問題:

  • 用戶體驗問題:當用戶看到了 file 地址,會對暴露的地址產生不安全感和不自在。
  • 安全性問題:由於 file 協議上直接帶上了本地路徑,任何用戶都可以看到這個文件所在的文件路徑,會存在一定的安全隱患。基於如上問題的考慮,採用虛擬域名的機制而不直接使用 file 路徑來訪問。虛擬域名是一個符合 URL Scheme 規範的 HTTPS 域名地址,例如 https://xxxxxxx.h5app.example.com

Nebula 裡面的 H5 容器和離線包,在傳統的 Hybrid 框架的基礎上進行了極致的優化,使整個 H5 應用具有如下特點:

  • 對網絡鏈路強依賴的弱化
  • 增強對設備能力的支持
  • 增強的用戶體驗

在性能方面,Nebula 在支付寶中經過了億級用戶的考驗,crash 和 anr 以及其他穩定性指標有保障。Android 平臺基於 UCWebview 深度定製,crash 率和 anr 量遠低於系統webview,擁有解決系統 Webview 問題的能力。圖中展示的就是在 Android 端,UCWebview 和系統 Webview 之間崩潰率和 ANR 率的對比,穩定性的優勢顯而易見。

支付寶移動端動態化方案實踐

最後看一下小程序與 Nebula支付寶小程序複用 Nebula 容器技術棧,重構了開發方式,對外暴露有限個 jsapi 接口,讓 app 開發更簡單,更加便捷利用支付寶的能力,進而發佈、推廣、運營。小程序本質上是也是一個 H5 App 離線包,但是有一些自己的特點。

  • 小程序是為第三方 App 服務的,運行在獨立進程,它的穩定和閃退不會影響到主 App,也支持二方 App 運行在主進程。
  • 小程序是支持保活的,極大的提升二次打開的體驗。

mPaaS技術架構與助力

Nebula 有這麼大優勢,現在不僅在螞蟻金服內部使用,也能夠提供給外部來使用。

首先什麼是 mPaaS 呢,mPaaS 全稱是 Mobile Platform as a Service 。是螞蟻金服獨創的移動研發平臺,它源於支付寶 App 近 10 年的移動技術實踐和思考,為移動開發、測試、運營及運維提供雲到端的一站式解決方案,能有效降低技術門檻、減少研發成本、提升開發效率,協助生態夥伴快速搭建穩定高質量的移動 App。

支付寶移動端動態化方案實踐

在 mPaaS 中,我們將 Nebula 的 H5 容器jsapi離線包小程序這些模塊作為一個單獨的組件來進行輸出,在客戶端中進行配置。任何一個 App 通過 mPaaS 插件,添加對應的模塊,集成這些功能,只需要這樣簡單的操作,就可以讓你的應用具有和支付寶一樣強大的動態化能力。

支付寶移動端動態化方案實踐

同時 mPaaS 提供的小程序模塊,允許用戶把運行在支付寶上的小程序,無縫的遷移到自己的 App 中,做到【跨平臺跨應用】開發,提高代碼的複用能力Nebula 組件化輸出,配合 mPaaS 提供的 MDS (移動發佈服務) 來實現動態更新。

mPaaS 提供的 MDS 服務,能夠讓每次發佈更新就像發郵件一樣簡單。

支付寶移動端動態化方案實踐

支付寶移動端動態化方案實踐

MDS 具有智能灰度發佈的能力,可以通過內部灰度,外部灰度多重驗證,保證在正式發佈之前,發佈的產品質量有充分的保證,同時提供多種升級策略,包括指定人群地域、機型,系統版本,網絡環境等多種規則。對於離線包來說,更新離線包的下載對網絡環境要求較高,包的大小越大,更新的成功率越低,在 mPaaS 中,我們採用增量差分的更新能力,減少數據冗餘及設備帶寬,在移動網絡條件下優勢明顯。同時保證更新功能的高可用性,升級接口可用率達 99.99%,在線分鐘級觸達。

下面是 Nebula 的生態基礎,首先在集團內部,我們已經支持了不少產品,同時通過 mPaaS ,我們也與外部客戶合作,將我們的技術能力輸出給他們,典型的幾個案例,包括 12306 客戶端,廣發發現精彩客戶端,上海地鐵,蘇州銀行等。

支付寶移動端動態化方案實踐

尤其是 12306,使用 mPaaS 改版之後,客戶端整體的體驗更加優越。12306 整個客戶端絕大部分都是使用的 H5 技術,他們就是使用 Nebula H5 容器 配合離線包來實現,無論是頁面打開速度,還是UI事件響應,體驗幾乎接近 native。在更新發布方面,12306 的 app 包很少更新,以 AppStore 上的發佈記錄來看,今年只提交了兩個版本,基本上都是通過動態化的方式完成業務的迭代發佈。

總結下來,螞蟻金服 mPaaS 中就是通過「Nebula H5容器 + 離線包 + 小程序 + MDS」這樣的方式來實現移動端的動態化方案。


分享到:


相關文章: