哈囉動態化容器架構實踐

背景介紹

圖片

哈囉的業務的多樣性體現到 APP 頁面上,我們會發現整個 APP 的頁面設計呈現的方式發生了很大的變化。早些年哈囉 APP 頁面的功能較爲單一,上圖是近幾年哈囉 APP 的頁面,可以看出頁面更加多樣化,很多業務的功能和信息都在這些頁面上展示出來,也有很多交互的能力。

圖片

這樣的業務發展趨勢及 APP 的頁面設計方式,給我們的技術團隊帶來了兩個痛點和挑戰。一是交付效率,複合型的頁面往往會涉及到多個業務團隊的需求,也會涉及到多個技術團隊去合作開發,效率就會下降。同時,這些頁面都屬於流量曝光型頁面,產品側需要做產品的 AB 測試,儘快地去上線並回收數據。如果發現功能需要調整,產品就希望儘快變更,所以用戶觸達效率及交付速度都對產品的迭代有很高的要求。二是用戶體驗,哈囉的首頁及各個業務的一級頻道頁,都是一個業務最核心的流量頁面,對用戶的體驗要求很高,如多端一致性、穩定性和交互流暢度這些指標,相對於其他三四級頁面來說,對穩定性的要求也會更高。

技術方案

技術選型的兩點思考

圖片

面臨這些痛點和挑戰,我們想到了一些解決方案,首先介紹一下技術選型的思考。一是我們要做一個架構,需要知道架構的能力邊界在哪裏,要解決怎樣的困難和實現怎樣的目標。這裏列出了現在成熟的客戶端 APP 的技術體系。從服務端來看,主要包括幾個能力,最底端的是中間件的能力抽象,上面是業務微服務的能力抽象,再上面是面向端的能力抽象,比如我們通常會做一層 BFF 來面向端的接口封裝,一層 CDN 來面向端的數據高效訪問的能力抽象。從客戶端來看,現在成熟的 APP 基本都有一套自己的組件化框架,做一些通用能力的沉澱,我們想要設計和實現的容器框架就是在組件化框架的上面,它的主要目的是承載各個核心頁面的展現和相關的業務邏輯,這是整個容器的能力邊界的大致界定。

我們希望這個容器首先是標準化的,通過標準化的手段來儘量抹平業務的複雜性帶來的問題。二是隔離的虛擬化技術,儘可能提高自身運行的穩定性。這是容器的兩個特點,也是我們選定了在這個範圍做容器封裝的技術。

圖片

我們的容器既然要承載整個頁面的渲染,應該用什麼技術來實現動態化渲染,這是第二個技術選型的思考。其實業內也有很多成熟的技術方案。我們可以從三個維度對這些技術進行歸類,一是動態化能力,剛纔也提到這是很重要的考慮點。二是原生體驗,因爲我們對整個頁面的流暢度、穩定性都有極高的要求,如果在原生體驗上做不到,那這個技術選型就不合適。三是開發成本,我們的成本投入也是有上限的。比如說大家比較熟悉的 Web 容器的方案,是比較容易引入到整個移動端裏的,它的優勢就是動態能力,相比整個原生的開發,它天然就具備動態更新的優勢。還有像 React Native、Weex 前幾年也是非常火,它的技術選型是在整個原生體驗和動態能力做了取捨。DSL 方案相對於前面兩種又各有優勢。

我們怎麼去做技術選型主要有兩個考慮點,包括投入成本和關鍵收益。一是投入成本,要結合自己業務的狀態和團隊的人力投入來考量,它需要考慮整個技術研發項目的成本,從頭開發還是在已有的架構上做升級,成本是完全不一樣的。其次現有系統的升級風險,對現有技術架構兼容性,對業務的影響都需要考慮進去。二是關鍵收益,任何技術項目都有很多收益,我們要考慮做這個系統,哪些技術能力是主要的,哪些是次要的,哪些是可有可無的。這樣分析後我們可以看到爲了保證用戶體驗,性能優先一定是最先考量的關鍵收益。其次我們要提升效率,儘可能降低團隊合作的邊界成本。同時我們希望架構可持續地去演進,來滿足業務不斷增長的訴求。基於這兩個考慮,我們最後選擇了 DSL 方案。

架構模型

圖片

移動端的核心框架有渲染層、協議層和邏輯層。渲染層是解決靜態渲染和動態渲染如何實現的,協議層是提供一些標準化的接口封裝,方便模塊的運行、通信以及擴展。邏輯層是整個容器框架自己運行的時候,它的狀態管理、數據管理、日誌管理各方面的一些能力的封裝。監控層是整個容器框架自己內建的一套監控體系,我們在這個體系上也搭建了很多可視化的工具和用戶觸達的能力。模塊層更多的就是模塊的管理。

動態模塊的實現和優化

圖片

上圖是容器渲染層動態模塊的渲染過程。首先還是獲取配置,也是剛纔整個頁面配置裏單一模塊的配置信息。這個信息裏的主要格式有兩部分,一是節點信息,決定了這一個渲染素裏面每個節點的元素類型,它可能是一個空的容器、一個文本,也可能是一個圖片。二是佈局信息,我們用 Flexbox 的語法來描述所有節點之間相互的關係。我們把配置信息解析出來生成了配置樹,就是把配置文件變成數據模型。接着是動態綁定,最後會生成一個渲染樹。在這個過程中會遇到一些性能問題,如中低端的安卓機,渲染性能較 iOS 機型會出現明顯下降。

圖片

我們從多個維度進行了優化工作,一是數據預取;第二是渲染優化,將前置的渲染操作步驟放到後臺線程來處理,並鋪平頁面元素的層級;第三個是數據更新策略的控制,包括版本管理、虛擬節點、動態綁定和 Diff 算法。

圖片

我們把這個卡片上屏之後,用戶需要交互能力,於是我們設計了一套 action 指令的方式來實現,通過預埋在配置信息裏的路由命令來實現手勢識別和相應的頁面跳轉操作。action 指令能解決 80% 的場景需求,但在某些場景下不太好用。

圖片

比如這樣的頁面,有一個優惠券可以領,當點擊紅色去領取按鈕的時候,卡片就會發生變化,比如按鈕會置灰,卡片的樣式也會發生變化。這種場景我們通過實現一套 jsruntime 來進行支持,通過動態獲取腳本來實現類似的操作。

容器邏輯層

圖片

這張圖是容器邏輯層的模型圖,可以從幾個維度理解容器邏輯層的運作方式。

第一是初始化,容器在啓動時進行初始化,整個模塊首先要進行自注冊,我們在適當時會獲取相應的配置數據,接下來會走前面介紹的流程,根據模塊的 ID 做模塊的初創建,根據算法來判斷是不是要上首屏,然後進行模塊上屏。

第二是運行時的狀態,一個模塊運行時主要有四個能力。一是它的佈局和樣式信息要維持,二是它的業務數據要維持,三是生命週期的狀態,包括它的顯示、隱藏、創建、銷燬,四是事件監聽,我們基於一個模塊通信的總線來實現整個模塊狀態的變更和相互關係的關聯。此外容器有狀態管理的機制。

容器協議層

圖片

第三層是容器協議層,我們設計這一層的意義是想讓模塊開發更加標準化,無論是平臺方還是業務方,能降低業務開發的複雜度。我們主要抽象了四層容器協議層,首先容器的佈局協議和數據協議相對比較好理解,佈局協議解決了佈局的一些信息,如模塊單元的大小、位置。容器的數據協議就是容器配置數據的填充,如單元格數量和內容;生命週期協議,包括創建、加載、顯示、消失和銷燬。生命週期協議有很多應用的場景,比如性能監控和曝光計算。事件協議,事件總線的運行是依託事件協議的,比如像模塊事件、定時器事件。

容器運行

圖片

我們從全局看一下容器運行是怎麼做的,這裏會看一下前端和服務端做的事情。前端會有一個配置平臺。策略中心由算法驅動決定整個模塊排序。業務微服務提供顯示模塊具體業務數據的來源,所有的信息都會融合成一個 BFF 層。端啓動後,比如首頁用了容器框架,啓動之後它會做容器的初始化、模塊的初始化流程,模塊運行時又基於事件狀態這樣的管線來做一些狀態的變更和模塊的通信。

研發流程的改進

圖片

我們設計了整個框架,新的系統對研發、測試、運維的工作方式都會帶來很多的變化,很多環節上進行了生產提效。綠色標註的是移動端常規的發版流程,我們看到涉及到的節點和團隊都非常多,跨團隊的合作會遇到很多問題,發版速度並沒有想象那麼快。在新的系統下,我們通過在線系統做的變更,這個環節的節點就會少很多,而且更新效率會快很多。

輔助工具

圖片

在整個開發過程中,我們也做了很多工具來提升開發的體驗和效率。剛纔也講到開發可以去配置平臺做配置,我們本地客戶端也集成了一個調試工具,會預覽渲染的動態卡片的樣式。

發佈和監控

圖片

發佈上線的流程不同於傳統的客戶端發版,它變成了一個在線系統的發佈流程。除了發佈的變更,我們也做了一些監控分析的能力爲它保駕護航,我們會採集性能的數據、穩定性的數據和異常的數據,在這些數據上建立可視化的分析能力和告警觸達能力。

項目實踐

圖片

2020 年我們做了首頁大改版,整個頁面會變成右側這樣。我們希望首頁能夠承載流量曝光、業務分發、廣告營銷各方面的能力,首屏的模塊會變得非常多,所以整個頁面信息的多樣化和邏輯的複雜度會高很多。基於這樣的背景,我們在 2020 年做了容器化架構的設計和升級。容器化架構升級主要分爲兩個階段,2020 年做了跨端統一的客戶端的框架,2021 年做了容器動態化相關的能力,進一步提升研發效率。我們計劃在前後端各個平臺,包括運營平臺、算法平臺等各方面去完善,包括低代碼的開發工具,把這個系統做得更好用更高效。

圖片

在 1.0 階段,我們主要爲了支持業務的升級,實現兩端統一的容器框架,可以把所有業務都呈現在整個框架上面,同時具備一些基本的標準,比如協議層的協議,還有整個模塊容器運行的狀態。基於這個事件驅動的模型,2.0 階段我們做了模塊化,再之後我們增加了動態化能力,進一步加快交付效率和降低研發成本。3.0 階段我們去完善前後端各系統。

圖片

回顧整個項目,我們在覆盤的時候總結了兩個經驗。一是要做取捨,業內也有很多現成的方案可以考慮,但並不是每一個都可以拿過來用,所以做技術取捨非常重要。要結合自己團隊的能力和目標來做取捨,並不是越複雜越好。二是我們要持續去做架構的升級,要看長遠些,我們的目標是持續推動業務的增長。我們整個首頁支持的業務線有 10 多個,上線之後一年多的時間裏迭代了 100 多次,保持了極高的穩定性,同時團隊的研發效率提升 30%,技術改造取得了很好的效果。

未來展望

圖片

最後介紹一下未來的展望,一是原生 SDK 可以做的工作,不斷提升穩定性,降低崩潰率和異常率,同時邏輯動態化上還有很多可以做的工作。二是完善工具箱,比如 IDE、數據可視化等。三是建設生產力平臺,讓搭建平臺更加簡單易用,同時要提高系統自動化能力。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/rwT0IyrosnVwjrRy2C4IKg