不要寫死!天貓App的動態化配置中心實踐

不要寫死!天貓App的動態化配置中心實踐

2016-03-15 高嘉峻 移動開發前線

版權聲明


本文爲天貓無線技術專家、蘋果核博主高嘉峻的投稿,未經授權禁止轉載


不要寫死,一個永恆的話題。動態化,也是一個涵蓋了界面,功能,數據,配置諸多方面的一個寬泛話題。


在之前的一篇《解耦神器 —— 統跳協議和Rewrite引擎》(http://pingguohe.net/2015/11/24/Navigator-and-Rewrite.html)中提到了我們的配置中心。這篇文章就跟大家聊一聊手機天貓在配置動態化上的心路歷程。

動態化就像野心一樣會膨脹

最初移動App就是一個老老實實的App,一切都硬編碼在客戶端,只有業務數據是從API而來。

漸漸的就會發現,這裏的Tab文案需要動態調整,那裏的文本顏色需要個性定製。於是我們就在數據接口里加上一些信息來控制客戶端邏輯。

當動態調整發揮作用,我們就發現這玩意兒簡直太棒了,客戶端邏輯居然也不需要版本依賴了!於是更多的邏輯開始未雨綢繆,開始在各自數據接口裏預先埋下控制信息。

那些沒有與API數據交互邏輯的靜態功能就很不爽,天生的純客戶端邏輯,難道就活該不能動態化?於是開始考慮專門爲動態化去設計一個API,專門傳輸控制信息。

後來還在後端還做了一個可視化的編輯界面,管理這些專門的控制信息,雖然簡陋了一點,也比修改那些混在數據API裏的信息要方便的多。

當專門用來傳輸控制信息的API和管理界面投入使用,漸漸的那些原本混在數據API裏的控制信息也加了進來 —— 一個叫做配置的功能就這麼誕生了。

天貓在配置這件事上投入了很多,成長至今,我們的配置中心也經歷了漫長的成長過程,現在配置中心是一個支撐多款應用多個平臺超過150個業務模塊的系統。在這個配置中心裏,有大到超過100條跳轉規則的Rewrite引擎,小到僅僅配置了一個狀態位的緩存開關;強業務相關的頭圖鏈接,強技術性的安全模式級別;最前端的App主題風格,最後端的日誌打印策略;等等。

最簡陋的配置文件

手機天貓第一個可以被稱爲配置中心的系統並非一個獨立運行的應用,而是寄生在一個被稱爲TMS的類似CMS的前端平臺上。最初的配置是每個業務在這個TMS上創建一張頁面,以JSON方式輸出到CDN,客戶端代碼按需下載這份JSON文件,從而實現動態化。逐漸我們發現,類似的需求越來越多,多個業務都在以這樣的方式做動態化。

許多人在重複做同一件事,那麼這件事就一定值得抽象。基於這樣的邏輯,我們抽象了一個可以支撐多個業務的“配置中心”,同時把功能從TMS遷移到了另一個更輕量的前端平臺——TWP上。在這個平臺上,所有模塊的配置都被描述爲一張二維表,每一個模塊可以在模版中訂製列,而每一行就是該模塊下的一條配置信息。每一次配置信息發生變更,這張二維表的數據會被提交到模版中的每個模塊訂製的一個JS函數,這個JS會針對二維表提交來的數據做校驗和簡單的格式化。

這個配置中心通過互相配合的兩張頁面模版最終生成一份被存儲在CDN的配置文件。

  • 一張頁面做“模塊配置”,用來管理接入配置中心的模塊信息。包括:模塊名稱,列配置。

  • 另一張頁面做“數據配置”,通過讀取“模塊配置”的信息生成一個支持多sheet的二位表簇,同時還持有每一張二維表,也就是每一個模塊,提交後的一段格式化JS函數。

每一次在“數據配置”頁面填寫數據並保存後,二維表簇的全部數據會被提交到格式化函數中,所有模塊的JS函數會各自執行,並把結果拼裝成一段完整的JSON,輸出到CDN上。

在這個簡陋的配置中心裏,我們最多支持了50-60個模塊的配置數據,數據量也超過了50K。由於配置數據是靜態的,而且無法增量更新,客戶端的流量問題非常嚴重。我們不得不再通過一個簡單的Web應用,通過讀取配置數據中的一個版本號(上圖,也是人肉配置的,需要每個修改配置的人修改這個版本號加1)比對客戶端上行的本地版本號,來判斷是否有配置變更,從而決定是否讀取這份完整的配置文件並下發到客戶端。

橫向擴展的配置中心

需求在膨脹

  • 接入的模塊越來越多,配置文件尺寸爆炸,客戶端難以承受

  • 線上版本增加,出現需要分平臺分版本投放的情況

  • 業務複雜性上升,二維表無法滿足業務需求

新的業務需求推動配置中心的一次大重構,開始重新梳理配置信息的數據結構,並建設獨立應用。

新配置中心

配置中心的數據結構必須兼顧統一性個性化。統一的數據結構是抽象管理邏輯的基礎,針對統一的數據結構可以設計出通用的管理界面,存儲邏輯;而具有一定的個性化能力才能針對不同的場景更好的滿足業務需求。

模型

基於這樣的考慮,我們設計了Key-List-Object的三層數據結構。也就是說,整體上配置數據是一個Map,Map中的每一項都是一個List,而List中的項則不規定結構,可以自由發揮。Key-List-Object結構對應到業務上:

  • Key - 表示模塊名

  • List - 表示模塊數據

  • Object - 表示模塊中的一條配置項

配置項,也就是Object是整個數據模型中的原子。

此外,爲了支持跨平臺和版本的需求,還設計了應用-平臺-版本-模塊的元信息模型。

  • 應用 - 這個系統可以支撐多款應用

  • 平臺 - 如:iPhone,Android Phone,iPad,Android Pad

  • 版本 - 就是App的軟件版本

  • 模塊 - 對應到數據結構的Key上

元信息模型和數據模型結合起來組成了完整的配置中心數據模型。數據項直接關聯應用,模塊和版本號三個元信息,版本號關聯平臺,模塊關聯應用。在這樣的關聯下,任意一個請求到達後:

  • 提取請求元信息:應用,平臺,版本號

  • 根據提取的應用找到關聯的模塊列表

  • 根據平臺,版本,模塊獲取全部相關配置項

  • 把全部構建成Key-List-Object的結構返回

強大的橫向能力

在這樣的技術方案下,這個新配置中心可以滿足幾乎全部橫向需求,支撐多個應用,多平臺,多版本同時管理。

修改某一個配置項並在多個版本同時生效,這樣的操作非常常見,而在新技術方案下,給每一個版本的App都分配了獨立的配置項數據。爲了解決這個問題,我們給所有有關的配置項設計了一個獨立的關係,當對某一個版本中的某一個配置項進行查詢,同時可以查詢到與之關聯的其他版本中的項。修改某一個配置項也可以同步到同一個關係下的其他關聯項。通過關係解決了對配置信息的關聯處理。

全個性化的配置項

以上的模型滿足了統一性,而個性化則在配置項上體現。在Key-List-Object結構中配置項沒有硬性的格式要求,所以每一個項都可以有其個性結構,只需要滿足JSON Schema的要求即可。

這樣的設計也可以保證對List沒有需求的場景,可以在首個配置項中有最高程度的設計自由度,定義適合業務的結構。

增量更新

之前說到新配置中心還要解決配置數據尺寸膨脹的問題。而隨着業務增長,配置中心所支撐的業務模塊已經超過了150個。在這樣的體量下,一份完整的配置文件已經接近200KB。顯然,每次都加載這樣的一個文件是不現實的,因此我們開發了針對模塊級別的增量更新功能。

任意一個模塊發生數據更新後,將向系統提交一次版本變更請求,整個配置版本號加1。配置中心記錄了每一次版本變更的模塊信息。當數據請求到達配置中心後,系統將比對當前最新版本和請求上行的App本地版本,並計算出版本差之間發生變更的模塊數據,構造一次增量數據返回。

在全部模塊中,最大的一個模塊數據不超過20KB,頻繁更新的模塊數量不多於10個,增量功能節約客戶端數據流量超過90%。

縱向延伸的信息通道

至此一個功能完善的配置中心初具規模,然而隨着配置中心接入的業務的增長,一個新的課題擺在我們面前。配置中心已經託管了幾乎整個App的配置信息,系統的橫向擴展只能積累量變,要進一步刺激業務能力升級就需要配置中心縱向擴展,在靜態配置之外的領域具備更強的功能。

縱向能力擴展的思路也有不同。發展配置中心繫統本身,針對需求擴展外延是傳統思路。然而我們認爲這樣的做法不能最大限度的發揮配置中心所具備的的能力,資源產出比太低。如果可以調動既有的其他系統的,推動既有系統的無線化,發揮配置中心的通道能力,就可以調動前無線時代我們積累的大量成熟系統能力,讓這些能力迅速在無線平臺上發揮作用。這種做法不僅充分擴展了配置中心的縱向能力,又推動了既有系統的無線化升級轉型,事半功倍。

對配置中心的縱向改造,我們從三個方面入手。

全開放的服務接口

依據所承擔的功能,把配置中心拆分成網關、核心服務和界面系統三個部分,並對其進行服務化改造。每一部分都具備獨立提供服務的能力,而他們之間的配合也通過服務化的接口來實現。

如此一來,每一個部分所具備的能力都都可以提供給配置中心繫統以外的其他系統,而且拆分後的系統,每一部分的發佈頻率,系統要求,應用特點各有不同,可以針對性更強的進行系統優化。

提升數據通道穩定性

舊的配置中心設計中,網關直接返回核心系統計算出的配置數據,只是通過內存緩存來提升訪問效率和穩定性。而新的設計下配置中心將爲更多業務提供數據通道服務,必須選擇更安全可靠的通道方案。

我們決定把靜態配置數據按照業務切分,以橫向屬性組合爲標示,投放到CDN上。通過網關下發CDN鏈接,App端SDK拿到鏈接後自行下載數據。從而降低核心模塊的壓力,提升穩定性。

高可定製的操作界面

此前,配置中心的界面趨於同質化,誠實的還原了Key-List-Object的數據結構,而配置項的編輯界面則是一個標準的JSON Editor。爲了提升可用性,我們獨立設計界面系統。

在這個界面系統中,業務方可以使用標準的JSON Schema來定義一張操作界面,也可以通過撰寫HTML模版實現個性化更強的界面。界面的表單數據將被提交到一個負責格式化和校驗的JavaScript方法中。在這個方法中表單數據被處理成系統所需要的配置數據,投放給核心服務。

不要寫死,永恆的話題

不要寫死,一個永恆的話題,這個話題會一直持續下去。而動態性這件事,是移動設備App當下最熱門的話題。在PC時代,我們的系統經歷了C/S到B/S的轉換,終於實現了最大程度的動態化。而在無線時代,移動設備有他獨特的屬性,B/S模式無法滿足無線時代的業務需求,至少當下是這樣。那麼Native動態化這條路,就還需要我們堅定的走下去,這條路的盡頭可能是另一個B/S模式,也可能我們找到了完美的Dynamic Wireless C/S模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章