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