開發與維運

流式場景下端雲一體搭建體系

作者:閒魚技術錦逸/碼寶

一、背景

隨著閒魚業務的高速增長,業務的數量和複雜度,都急劇增加,研發側在業務支撐上出現了兩個明顯的變化:
一方面,如首頁、搜索之類的傳統流量型頁面,試錯和調整變得更加頻繁,只有卡片級的動態化能力已經不能滿足需求,更多的頁面級結構調整撲面而來,僅以首頁為例,去年大約有一半的時間,都在做頁面結構調整。
另一方面,更多的DAU帶來的是更多的垂直業務的增長,如同城、會玩、優品、租房、二樓等等,它們也都需要自己的流量型“首頁”,而在這個過程中,同類型結構和能力的頁面代碼大量重複,開發維護成本非常之高。

那麼有沒有一種方案,能夠快速cover各個業務場景裡的流量型頁面,不僅能夠適應這種快速多變的大量結構性調整,並且能夠快速試錯和嘗試,儘可能減少重複代碼的方案呢?答案是有的,基於流量型頁面重展示,輕交互的特點,我們的解法是建立一套端到端的頁面級描述協議,加上對接協議的雲端搭建平臺來對流量型頁面結構進行動態調整和渲染。一方面,協議的調整可以直接映射為頁面結構的調整,以達到less code甚至no code對頁面結構進行調整的目的。另一方面不同業務場景,可以用通用協議來進行橫向擴展,減少開發和維護的成本。

二、流式場景協議的擴展

閒魚去年的時候,基於流量型頁面,提出過一套三級協議的容器化解決方案,當時的三級協議包括:Page、Section和Component,能夠較好的描述單頁面的情況:

  • Page層協議主要包含整個頁面Sections信息,以及下拉刷新、上拉加載更多等配置信息;
  • Section層協議包含當前Section的佈局信息、初始化Event、LoadMore Event及Components等信息;
  • Component層協議與具體業務相關,對於容器來說是黑盒的,具體如何渲染會交給業務方處理;默認提供DX解析渲染Handler。

容器中,事件中心基於事件傳遞的方式,數據中心基於MVVM的數據驅動進行實現,在UI渲染方面,閒魚將列表容器與動態模板渲染DXFlutter相結合,實現頁面渲染及數據更新後的頁面刷新能力。

為了適應複雜的多頁面場景以及容器嵌套的情況,我們在之前提出的三級協議的基礎上,擴展了四層協議的設計:Container、Page、Section和Component。新設計的Container層協議主要包含多個頁面Page的信息,以及頁面Page對應的tab等配置信息:

|-- Container
|-- Page
|-- Section
|-- Component

image.png

由於在Container這一級,我們需要對多個Page頁面進行佈局,這裡目前能支持三種形式:

  1. 單頁面,每個頁面單listview形式
  2. pager+tab+多頁面形式,每個頁面是單listview形式
  3. 頁面內包含子容器,也就是嵌套容器的形式

我們以最複雜的嵌套容器的情況為例,嵌套的子容器對他的父級的頁面而言,實際上是一個Component(卡片),但是它的內部數據結構是一個完整的Container的容器結構,在協議上,我們給它設置的type="sub_container",這個時候會用默認的SubContainerRenderhandler(子容器渲染器)對自容器進行解析和渲染,並在過程中處理對應的手勢問題,這裡我們會給父容器和子容器在協議上分別進類型指定,並提供類型對應手勢響應能力。子容器中的頁面間的切換消息通過通知對外發送,如果是tab+pager的形式,只需要在tab內對廣播消息設置對應的監聽即可,同時子頁面也可以通過通知消息接收切換頁面的指令,這樣的組織形式就能讓tab和pager在解藕的情況下相互通信。

三、雲端平臺的設計

整體設計

目前流量平臺以二方包的形式對業務服務提供支持,運營和開發可以在流量平臺搭建頁面和配置對應的資源位數據,在數據修改之後,平臺會將修改的部分先寫入到TDDL,然後再主動同步到cache,而cache可以被部署在業務服務的平臺client二方包讀取到,正常的情況下,cache存在,則業務服務在響應閒魚客戶端請求的時候,只需要讀取緩存即可,只有在緩存不存在的時候,才需要主動拉取對應的資源配置數據。

image.png

Client二方包設計

其中部署在業務服務中的client二方包具備配置獲取、分流計算、動態註冊、遠程調用等基礎能力,除此之外,還對容災兜底和異常監控都有對應的設計。依賴二方包的形式,業務方服務就能夠以解藕的方式來獲取流量平臺的資源和配置信息。
image.png

分流的設計

由於流量型頁面需求多變,試錯的場景普遍存在AB實驗的需求,我們在雲端平臺設計了一套流量分流的體系,來最大限度的降低流式場景下AB實驗的成本。

image.png

一個閒魚端側用戶在請求容器頁面時,會將對應的用戶、版本、lbs等相關信息通過統一的協議上傳到雲端平臺,平臺拿到這些信息之後,會經過概念層、分流層、實例層和資源層,最後所有實例都會關聯資源和發佈計劃。這樣請求最終能映射到某一個確定的投放方案上,從而讓對應的用戶看到確定的頁面搭配,從而達到雲端實驗分流的目的,最終讓用戶看到他應該落到的實驗頁面。這樣新建或者調整頁面的AB實驗,我們只需要在雲端配置對應的實驗頁面需要滿足的流量條件即可,很大程度上降低了業務試錯的研發成本。
image.png

安全容災

流量型頁面一般承載著對應業務的業務入口的角色,是門戶,它的穩定性不言而喻,所以整體端雲一體的設計中,也少不了對容災和兜底的考慮。

雲端容災

正常情況下,客戶端請求平臺,通過業務方服務接口把userid、城市、設備等信息上傳到雲端,根據之前的流量設計以及二方包的緩存設計,如果命中的方案,二方包能獲取到緩存,則會直接返回緩存資源數據,否則會去流量平臺請求資源數據再返回。
截屏2021-05-25 下午12.07.22.png

在異常情況下,或者沒有拿到對應的緩存,那麼這時候會用到我們在緩存製備好的的一份兜底數據,兜底數據會在平臺操作變更時,通知業務方服務端去製備新的兜底數據以及去除舊的兜底數據。
截屏2021-05-25 下午12.10.19.png

客戶端容災

客戶端容災主要考慮到網絡異常或者接口服務不可用的情況,依然需要保證頁面的正常展示,這個時候我們在端側設計了三級緩存:內存緩存、磁盤緩存以及預置緩存。內存緩存和磁盤緩存都會在接口成功回調之後做保存動作,在失敗的情況下會優先去獲取內存緩存和磁盤緩存,而當這兩部分都獲取不到時,就會嘗試獲取打在apk包中的預置緩存數據,這樣保證頁面不管任何情況下都能正常展示。
image.png

客戶端與雲端平臺協議交互

由於端側容器化協議是基於事件進行交互的,那麼在雲端平臺加入之後,整體事件交互的邊界就被進一步拓寬。舉個例子,以點擊觸發關注列表中的某個卡片出現關注標記為例。傳統的做法,一般是客戶端在端側寫好關注和刷新邏輯,然後在點擊的時候去調用寫好的刷新方法。但是如果用端到端的協議來實現,則會變成點擊將列表接口在當前卡片上綁定的事件回傳給平臺,這個事件是什麼,對端側來說是透明,在當前場景就是一個關注的事件,那麼這個事件會通過點擊事件帶到雲端,雲端拿到對應的事件key之後,會下發對應的數據,然後端側只對數據進行刷新,刷新之後,就會讓當前卡片出現關注標記。這樣的好處在於,減少業務依賴端側的版本發佈,最大程度的使用數據驅動的設計,減少依賴,提高複用性。這樣的設計加上容器化協議對頁面結構的描述和渲染,在重展示輕交互的流量型頁面,將會大大減少端側邏輯耦合,提高業務開發的效率。

總結和展望

目前,端雲一體的容器化搭建方案,已經在閒魚多業務場景落地。此前的兩個問題也得到了解決:
1. 頁面結構調整的動態化能力:以首頁為例,在容器化協議落地之後,再做頁面結構調整,我們只需要簡單修改雲端平臺的配置加上很少的代碼改動即可生效,大大減少了業務維護的成本。
2. 橫向業務場景的流量型頁面支撐:藉助雲平臺配置搭建和端側容器化渲染協議,現在大約只需要平時一半的開發時間,就能完成一個全新業務場景的搭建,更多的頁面骨架型代碼,都沉澱在以容器化協議為基礎的SDK中。
流式場景下端雲一體搭建體系,降低了端側多業務中流量型頁面這種特定場景下的冗餘代碼邏輯。整體雲端一體的容器化搭建方案,使得less code甚至no code快速調整頁面結構以及快速搭建新業務場景中以展示為主、輕交互動態化運營流量型頁面成為了可能。

Leave a Reply

Your email address will not be published. Required fields are marked *