APPKIT打造稳定、灵活、高效的运营配置平台
一、背景
美團App、大眾點評App都是重運營的應用。對于App里運營資源、基礎配置,需要根據(jù)城市、版本、平臺、渠道等不同的維度進行運營管理。如何在版本快速迭代過程中,保持運營資源能夠被高效、穩(wěn)定和靈活地配置,是我們團隊面臨的重大考驗。在這種背景下,大眾點評移動開發(fā)組必須要打造一個穩(wěn)定、靈活、高效的運營配置平臺。本文主要分享我們在建設高效的運營配置平臺過程中,積累的一些經(jīng)驗,以及面臨的挑戰(zhàn)和思考。
運營資源
簡單而言,運營資源可以理解為App中經(jīng)常變動的一些廣告、運營活動等等,譬如下圖中電影首頁頂部的Banner位,就是一個典型的運營資源。對于這類運營資源,它們有如下明顯特征:
基礎配置
基礎配置,常見的有入口資源的配置、網(wǎng)絡的配置等。相對運營資源來說,其變更的頻繁度相對較低,與時間、城市的關系也沒那么強。譬如下面大眾點評App-我的頁面里的入口。這類配置有如下幾個特征:
二、遇到的問題
在從0到1打造運營配置平臺的過程,我們遇到了很多“坑”。特別是在早期“刀耕火種”的時代,對于入口的配置,往往是通過“hardcode(硬編碼)”的方式寫死在代碼中。所以必然會遇到很大的問題,這主要體現(xiàn)為以下兩方面:
運營效率低
對于新的運營配置需求,研發(fā)同學需要開發(fā)對應的配置頁面,然后轉給運營同學進行配置的管理,最后運營人員對資源進行配置上線,其流程如下:
對于每個運營配置需求都要經(jīng)過需求評審、頁面開發(fā)、配置管理、上線的流程。同時,對于配置頁面的開發(fā),少則需要1到2天的開發(fā)工時,研發(fā)成本高。問題總結如下:
上線流程“粗糙”
在早期,運營配置上線流程需要研發(fā)同學參與。產(chǎn)品提出運營配置需求,研發(fā)同學通過修改代碼對配置進行變更,然后通過代碼上線進行發(fā)布。整體流程如下:
這種上線機制存在以下幾個問題:
三、我們的思考
針對以上問題,我們希望通過設計一個通用的解決方案,去解決上文闡述的各種運營資源管理的問題。我們把這個整體的項目稱之為APPKIT,寓意是App的運營配置工具(Kit)。通過不斷的實踐和總結,我們希望能從三個維度解決上述問題:
數(shù)據(jù)JSON化
隨著業(yè)務的不斷迭代,無論采用怎樣的數(shù)據(jù)字段組成,都無法滿足業(yè)務變化的字段(這里是指像標題、副標題、圖片、跳轉鏈接等)要求。對底層數(shù)據(jù)進行JSON化,其對應的數(shù)據(jù)字段完全可動態(tài)擴展,從而滿足業(yè)務不斷迭代的需求。JSON化隨之也會帶來運營位字段管理的問題,我們通過字段管理的工具來解決這個問題。
運營流程化
設計一套整體的流程管理機制,解決運營的投放、審核、發(fā)布和回滾的問題。通過流程化的機制,我們實現(xiàn)了“事前”、“事中”、“事后”的三級管理。
首先,在運營配置上線前,通過測試用戶的預覽功能,可以預覽上線后的實時效果。同時,通過穿越功能可查看將來時段顯示的效果。防止出現(xiàn)上線后鏈接出錯、視覺效果達不到預期等問題。
其次,在流程階段,引入審核機制,通過視覺和內(nèi)容兩方面的審核,保證投放數(shù)據(jù)的準確性。
最后,在運營配置上線后,如果發(fā)現(xiàn)問題,可以通過快速回滾,最大限度地實現(xiàn)“止損”。
接口SDK化
對于運營數(shù)據(jù),無論是通過數(shù)據(jù)庫的落地方案、還是通過分布式緩存的方案,都無法徹底解決服務中心化和服務抖動的問題。通過接入的SDK化,可以做到數(shù)據(jù)的本地緩存更新機制,解除對中心化服務的依賴,大大提升服務的穩(wěn)定性和性能。同時整個APPKIT服務變成可水平擴展,在擴展過程中也不會影響中心服務的穩(wěn)定性。
四、APPKIT架構
APPKIT運營配置系統(tǒng)整體框架如下(數(shù)據(jù)流向如箭頭所示)。從功能角度,大體上分為四層:數(shù)據(jù)層、服務層、接入層和監(jiān)控層。
4.1 數(shù)據(jù)層
數(shù)據(jù)層作為最底層的數(shù)據(jù)存儲,其保存了最基本的運營后臺數(shù)據(jù)、流程數(shù)據(jù)和線上數(shù)據(jù)。對持久化的數(shù)據(jù),我們采用MySQL進行存儲;對于緩存數(shù)據(jù),我們采用了Redis的解決方案。這樣數(shù)據(jù)層形成基本的兩級存儲結構:MySQL保證了數(shù)據(jù)的持久性,Redis保證了數(shù)據(jù)獲取的速度。
這里我們對底層數(shù)據(jù)劃分為三個不同域:后臺數(shù)據(jù),相當于草稿數(shù)據(jù),運營人員所有的操作都記錄在這里;流程數(shù)據(jù),運營人員操作完成后,提供發(fā)布流程,預覽及審核都在流程數(shù)據(jù)里進行;線上數(shù)據(jù),審核通過后,數(shù)據(jù)同步到線上數(shù)據(jù),最終C端用戶獲取到的數(shù)據(jù)都是來源于線上數(shù)據(jù)。
談到數(shù)據(jù)層,這里我們遇到了存儲上的一個小問題。按城市運營的每條數(shù)據(jù),都需要存儲具體的城市ID列表,其在數(shù)據(jù)庫里的存儲為 “1,2,3,4…… ”這樣字符串。而這種數(shù)據(jù)存儲在業(yè)務請求和條件過濾過程中,存在著如下兩個問題:
a. 大數(shù)據(jù)存儲對內(nèi)存的消耗
美團、大眾點評運營的城市成千上萬,如果每條運營的投放數(shù)據(jù)都包含大量的城市列表信息,對機器內(nèi)存勢必產(chǎn)生一定消耗。
b. 過濾性能問題
城市的過濾邏輯大體是這樣:用戶所在城市與從數(shù)據(jù)庫獲取到的城市列表(“1,2,3,4…… ”)進行匹配,在每次匹配過程中都需要做字符串“split”的切割操作。這種操作的特點是流量越大,對機器CPU的消耗越大。
解決方案:基于以上兩點考慮,再結合Java語言提供的BitSet機制。我們從數(shù)據(jù)庫里取出城市列表數(shù)據(jù)后只做一次“split”切割操作,將數(shù)據(jù)轉化為BitSet類型。這樣在實際過濾過程中只需要通過BitSet的get機制就可以判斷運營投放的城市是否包含了用戶所在的城市。通過BitSet機制,我們既解決了大數(shù)據(jù)存儲對內(nèi)存的消耗問題,又解決了城市過濾的性能問題。
4.2 服務層
服務層向下對底層數(shù)據(jù)進行操作;向上為接入層獲取數(shù)據(jù)提供接入能力。其提供四個服務能力:運營后臺、開放平臺、數(shù)據(jù)服務、APPKIT-SDK,如下表所列:
4.3 接入層
接入層主要為運營人員、業(yè)務研發(fā)提供接入能力。通過運營流程化為事前、事中、事后提供保障。一個運營資源從制作到最后在C端展示,需要經(jīng)過運營人員的投放、測試預覽、審核及發(fā)布的中間流程。這里對于一些敏感的運營資源,需要通過安全部門的審查。安全審查主要涉及到敏感詞的處理、敏感圖片的檢測等。對運營配置平臺來說,它完全是一個“黑盒模型”。這里主要涉及到兩種情況:
資源上線時
資源上線后
4.4 監(jiān)控層
APPKIT-SDK運行在業(yè)務機器上,這里就涉及到多臺機器的數(shù)據(jù)一致性問題。同時,隨著業(yè)務接入運營數(shù)據(jù)的增多,SDK對機器內(nèi)存勢必有一定消耗。基于服務的穩(wěn)定性考慮,我們對SDK運行時的投放內(nèi)容進行監(jiān)控,其主要監(jiān)控兩個指標:運營位數(shù)及每個運營位的配置總數(shù)。這樣做可以帶來以下幾個好處:
同時,對于非SDK的其他性能指標,我們采用統(tǒng)一的監(jiān)控平臺–CAT進行監(jiān)控,其中包括:APPKIT中心服務的調(diào)用QPS,機器的性能,網(wǎng)絡流量等通用指標。
五、底層模型–靈活性設計
5.1 從一個例子切入
數(shù)據(jù)模型往往與業(yè)務相關。業(yè)務越復雜,設計需要越簡單,這樣方能滿足復雜業(yè)務的各種變化。因為數(shù)據(jù)模型太過于抽象,如果直接進行述說會有些乏味,我們可以先從一個具體的業(yè)務實例入手。下面是大眾點評App頂部金剛位的截圖,對于這部分數(shù)據(jù),如何做到運營可配?
首先,我們對運營數(shù)據(jù)做需求拆解。對于這塊數(shù)據(jù),每個 “節(jié)點”(對應每個位置:如美食,技術上我們稱之為 “節(jié)點”),其基本的運營訴求如下:
上面這個運營場景算是非常經(jīng)典、復雜的一個運營場景了,如果這個問題解決了,其他問題自然就會迎刃而解。
5.2 技術分析
我們做一下進一步的技術分析:
首先,這里有節(jié)點,每個節(jié)點(Node)有其相應的內(nèi)容(Content),節(jié)點與內(nèi)容是“一對多”的關系。這里的內(nèi)容,我們指的是如標題、圖片、跳轉鏈接等信息,雖然是“一對多”的關系,但最后在同一個城市、同一個版本下(可選擇)只顯示一條內(nèi)容。為什么有這樣的需求?舉一個簡單的業(yè)務場景實例,以外賣為例,在新版本10.0的時候做了一個全新的外賣頻道頁面,其鏈接信息與老版本的完全不同,這里我們就需要按版本的不同配置兩條不同的內(nèi)容信息。
其次,節(jié)點與節(jié)點之間有兩層關系,其一為“平級關系”,如美食與外賣的關系,這種關系就是一種簡單的列表關系;其二為樹關系(Tree),如外賣與下午茶之間的關系。這里我們將角標(下午茶)視為一個節(jié)點,因為角標也需要按不同維度進行過濾,因此下午茶成了外賣的子節(jié)點。其實這里有一些特殊的地方,如果角標不需要按城市、版本等維度進行運營,那很簡單它就是一個內(nèi)容信息(類似標題)。
最后,我們談一談排序問題,對于這么多品類,如何排序,他們的優(yōu)先級是什么?我們需要定一個基本的基調(diào),每個節(jié)點都有一個基本的排序值(優(yōu)先級)。但深入業(yè)務分析,對于不同的人(群),每個人關注的點不一樣,需要一個“千人千面”的算法,來決定每個人所看到的內(nèi)容是其真正關心的內(nèi)容。所以,這種應用場景下的排序應該通過機器學習算法而得到。
5.3 數(shù)據(jù)建模
針對上面的技術分析,我們提出了一種節(jié)點(Node)-內(nèi)容(Content)-樹(Tree)模型,簡稱為N-C-T模型。如下圖所示:左邊為抽象的數(shù)據(jù)模型,右邊為以上實例的實現(xiàn)。
N-C-T數(shù)據(jù)模型設計的非常簡單,其中C和T部分都是可選擇的,這樣使得其靈活性比較強,可以應對業(yè)務變化的大部分需求。注意,這里我們只是對業(yè)務需求的宏觀表現(xiàn)形式進行建模,對于具體Node和Content里的有哪些字段(標題、副標題、圖片、跳轉鏈接),這些都是JSON化的存儲格式,可以滿足任意字段的擴展。
5.4 模型的應用與小結
通過以上經(jīng)典實例,我們可以很容易通過我們的數(shù)據(jù)模型解決這個問題。我們再回到文章最開頭的背景章節(jié)的運營場景,Banner位,如下:
這種Banner位,套用我們上的數(shù)據(jù)模型,它其實是一種只有一個Node節(jié)點、多個Content節(jié)點的模型。這也是一種典型的應用場景,為此我們總結了兩種應用場景。
其實,大部運營場景都可以套用以上兩種經(jīng)典的運營組合。
六、運營流程化
將運營資源的管理進行流程化,具有以下幾個好處:
數(shù)據(jù)域
對于流程化的實現(xiàn),我們是將數(shù)據(jù)域切分成三個不同的部分:后臺數(shù)據(jù)、流程數(shù)據(jù)和線上數(shù)據(jù),如下圖所示:
后臺數(shù)據(jù):我們可以簡單理解為草稿數(shù)據(jù),這里的數(shù)據(jù)多用戶可同時進行操作,也不會對線上數(shù)據(jù)有影響。
流程數(shù)據(jù):當用戶后臺數(shù)據(jù)編輯完成后,對數(shù)據(jù)提交一個發(fā)布流程,數(shù)據(jù)進入流程數(shù)據(jù)區(qū)域;這時可對數(shù)據(jù)進行測試預覽、審核等操作。
線上數(shù)據(jù):這塊數(shù)據(jù)是C端用戶真正獲取到的數(shù)據(jù),當流程數(shù)據(jù)審核通過后,數(shù)據(jù)會自動同步到線上數(shù)據(jù)域,完成上線操作。
上線流程
整個上線流程如下:
為了能平穩(wěn)上線,我們設計了一個測試預覽功能。當數(shù)據(jù)處于流程中時,用戶可以通過掃描二維碼加入到測試用戶名單,可對處于審核流程中的數(shù)據(jù)進行預覽,用美團、大眾點評App查看上線后實時效果,其實現(xiàn)的數(shù)據(jù)流如下:
七、穩(wěn)定性的演進
穩(wěn)定性是一個運營配置平臺最重要的能力,沒有穩(wěn)定性,其他任何功能都會失去實際意義。運營系統(tǒng)的穩(wěn)定性經(jīng)歷了不同的迭代時期,總結起來,可概括為以下三個階段:
7.1 經(jīng)典方案
這是APPKIT最早期的經(jīng)典方案,它的實現(xiàn)也非常簡單,如下圖所示:
C端用戶通過業(yè)務接入層獲取數(shù)據(jù),業(yè)務接入層通過服務調(diào)用獲取配置后臺數(shù)據(jù)(APPKIT服務),配置后臺數(shù)據(jù)服務讀取緩存數(shù)據(jù)。如果緩存數(shù)據(jù)不存在,則從數(shù)據(jù)庫中讀取數(shù)據(jù),同時將數(shù)據(jù)庫數(shù)據(jù)同步到Redis緩存中。這是經(jīng)典的數(shù)據(jù)獲取模型,但它有以下幾個缺點:
7.2 緩存方案
針對以上經(jīng)典方案的缺點,我們做了進一步的改進,對配置后臺數(shù)據(jù)服務做了一層本地內(nèi)存緩存,如下圖所示:
樣做可以解決數(shù)據(jù)調(diào)用的部分網(wǎng)絡時延問題,同時Redis緩存的抖動也不會影響整體服務的性能。不過,這個方案也有其自身的缺陷。
7.3 SDK方案
為徹底解決緩存方案的問題,尤其是服務中心化帶來的流量、容量等問題,我們將運營數(shù)據(jù)的獲取、Web緩存的管理集成進SDK。如下圖所示:
這樣的話,無論接入再多的業(yè)務,也不會對中心服務產(chǎn)生過大的流量壓力和容量壓力。SDK同時也解決了服務間調(diào)用的網(wǎng)絡時延問題。所有同步數(shù)據(jù)的網(wǎng)絡調(diào)用都是通過后臺線程異步完成,不會影響業(yè)務線程的正常處理邏輯。
不過,SDK方案也引進了如下的新問題:
為了解決數(shù)據(jù)的時效性和一致性問題,我們引入了監(jiān)聽更新機制,如下圖所示:
運營人員在運營后臺操作完成后,提交上線流程,流程發(fā)布后通過ZooKeeper的變化監(jiān)控發(fā)送一個變化事件;SDK通過監(jiān)聽變化事件,拉取變化后的運營數(shù)據(jù)更新到本地。這里,為了防止這種監(jiān)聽機制失效,我們也做了一個兜底策略:每分鐘定期進行一次數(shù)據(jù)同步。這樣保證數(shù)據(jù)最遲一分鐘內(nèi)就能實現(xiàn)同步。對于SDK本地緩存,我們設計了監(jiān)控上報機制,如下圖所示:
這里有兩條線路,其一為SDK在請求數(shù)據(jù)時,帶上數(shù)據(jù)的accessTime時間戳,APPKIT服務會根據(jù)accessTime時間戳判斷SDK本地數(shù)據(jù)是否過期。當accessTime時間超過24小時,說明這個運營位在一天內(nèi)都沒有使用,可以從本地內(nèi)存中進行刪除。其二為SDK定期進行監(jiān)控上報,上報SDK本地緩存的數(shù)目,這樣可以對SDK本地緩存進行監(jiān)控和告警。對SDK版本升級問題,現(xiàn)有的解決方案,是通過CI構建時對SDK版本升級進行提示(必要時進行強制),不過大部分運營位使用的都是基礎功能,在很大程度上不需要進行頻繁地升級。
效果對比
緩存方案與SDK方案的效果對比如下:
注: SDK方案的平均線為0.0是因為統(tǒng)計時舍入引起的,真實值其實非常小。
八、總結與展望
本文通過美團點評移動運營平臺的實踐,詳細介紹了我們在打造穩(wěn)定、靈活、高效的運營配置平臺過程中遇到的問題和挑戰(zhàn),同時本文也提供我們的解決思路:通過數(shù)據(jù)JSON化,運營流程化,接口SDK化分別解決了運營平臺的靈活性、高效性和穩(wěn)定性。APPKIT幫助產(chǎn)品、運營和研發(fā)提升C端的開發(fā)和運營效率,加速產(chǎn)品的迭代進程。
目前基于APPKIT的平臺化特性,對App的模塊化配置、Picasso的JS的管理、ABTest、個人中心入口管理、魯班(面向C端的Key/Value配置系統(tǒng))等業(yè)務提供了底層的數(shù)據(jù)存儲和數(shù)據(jù)獲取的支持,為移動端業(yè)務提供了運營配置的基礎保障。
同時,為了進一步提升運營效率,我們基于Picasso的多端(Android、iOS、H5、微信小程序)能力,正在構建移動化的運營能力。這樣保障用戶無論在什么辦公環(huán)境都能進行運營配置的管理。
作者簡介
- 國寶,美團點評移動運營平臺負責人,Java后端架構師,APPKIT項目發(fā)起人,負責APPKIT項目的架構設計。專注于高性能、高穩(wěn)定、大并發(fā)系統(tǒng)的設計與應用。
- 小龍,目前為APPKIT項目負責人,主要負責APPKIT項目開發(fā)、技術對接和實施、開放平臺等。專注于前后端全棧技術開發(fā),喜歡挑戰(zhàn)新的技術和業(yè)務問題。
總結
以上是生活随笔為你收集整理的APPKIT打造稳定、灵活、高效的运营配置平台的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty的实现原理、特点与优势、以及适
- 下一篇: Spring Boot整合MyBatis