
隨著美團外賣業(yè)務(wù)不斷發(fā)展,外賣廣告引擎團隊在多個領(lǐng)域進行了工程上的探索和實踐,目前已經(jīng)取得了一些成果。我們計劃通過連載的形式分享給大家,本文是《美團外賣廣告工程實踐》專題連載的第一篇。
本文針對業(yè)務(wù)提效的目標(biāo),介紹了美團外賣廣告引擎在平臺化過程中的一些思考和實踐。我們圍繞實際遇到的問題、思考過程以及具體的落地方案,從業(yè)務(wù)的標(biāo)準(zhǔn)化、技術(shù)框架、產(chǎn)研新流程的改造等三個方面進行展開,希望能為讀者提供思路上的借鑒。
1 前言
2 現(xiàn)狀分析
3 目標(biāo)
4 整體設(shè)計
4.1 整體思想
4.2 業(yè)務(wù)標(biāo)準(zhǔn)化
4.3 技術(shù)框架
4.4 產(chǎn)研新流程
5 效果
6 總結(jié)與展望
7 作者簡介
招聘信息
1 前言
美團外賣已經(jīng)成為公司最為重要的業(yè)務(wù)之一,而商業(yè)變現(xiàn)又是整個外賣生態(tài)重要的組成部分。經(jīng)過多年的發(fā)展,廣告業(yè)務(wù)覆蓋了Feed流形式的列表廣告,針對KA以及大商家的展示廣告,根據(jù)用戶查詢Query的搜索廣告,以及一些創(chuàng)新場景的創(chuàng)新廣告等多個產(chǎn)品線,并對應(yīng)十幾個細分的業(yè)務(wù)場景。從技術(shù)層面而言,一次廣告請求的過程,可以分為以下幾個主要步驟:廣告的觸發(fā)、召回、精排、創(chuàng)意優(yōu)選、機制策略等過程。如下圖所示:即通過觸發(fā)得到用戶的意圖,再通過召回得到廣告候選集,通過預(yù)估對候選集的店鋪打分、排序,再對于Top的店鋪再進行創(chuàng)意的選擇,最后經(jīng)過一些機制策略得到廣告結(jié)果。

2 現(xiàn)狀分析
在業(yè)務(wù)迭代的過程中,隨著新業(yè)務(wù)場景的不斷接入,以及原有業(yè)務(wù)場景功能的不斷迭代,系統(tǒng)變得越來越復(fù)雜,業(yè)務(wù)迭代的需求響應(yīng)逐漸變慢。在業(yè)務(wù)發(fā)展前期,開展過單個模塊的架構(gòu)重構(gòu),如機制策略、召回服務(wù),雖然對于效率提升有一定的改善,但是還會存在以下一些問題: 業(yè)務(wù)邏輯復(fù)用度低:廣告業(yè)務(wù)邏輯比較復(fù)雜,比如機制服務(wù)模塊,它主要功能是為廣告的控制中樞以及廣告的出價和排序的機制提供決策,線上支持十幾個業(yè)務(wù)場景,每種場景都存在很多差異,比如會涉及多種召回、計費模式、排序方案、出價機制、預(yù)算控制等等。此外,還有大量業(yè)務(wù)自定義的邏輯,由于相關(guān)邏輯是算法和業(yè)務(wù)迭代的重點,因此開發(fā)人員較多,并且分布在不同的工程和策略組內(nèi),導(dǎo)致業(yè)務(wù)邏輯抽象粒度標(biāo)準(zhǔn)不夠統(tǒng)一,使得不同場景不同業(yè)務(wù)之間復(fù)用程度較低。 學(xué)習(xí)成本高:由于代碼復(fù)雜,新同學(xué)熟悉代碼成本較高,上手較難。此外,線上服務(wù)很早就進行了微服務(wù)改造,線上模塊數(shù)量超過20個,由于歷史原因,導(dǎo)致多個不同模塊使用的框架差異較大,不同模塊之間的開發(fā)有一定的學(xué)習(xí)成本。在跨模塊的項目開發(fā)中,一位同學(xué)很難獨立完成,這使得人員效率沒有得到充分利用。 PM(產(chǎn)品經(jīng)理)信息獲取難:由于目前業(yè)務(wù)場景較多、邏輯復(fù)雜,對于信息的獲取,絕大多數(shù)同學(xué)很難了解業(yè)務(wù)的所有邏輯。PM在產(chǎn)品設(shè)計階段需要確認(rèn)相關(guān)邏輯時,只能讓研發(fā)同學(xué)先查看代碼,再進行邏輯的確認(rèn),信息獲取較難。此外,由于PM對相關(guān)模塊的設(shè)計邏輯不清楚,往往還需要通過找研發(fā)人員線下進行詢問,影響雙方的工作效率。 QA(測試)評估難:QA在功能范圍評估時,完全依賴于研發(fā)同學(xué)的技術(shù)方案,且大多數(shù)也是通過溝通來確認(rèn)功能改動涉及的范圍和邊界,在影響效率的同時,還很容易出現(xiàn)“漏測”的問題。?
3 目標(biāo) 針對以上的問題,我們從2020年初,啟動美團外賣廣告引擎平臺化項目,旨在通過平臺化的項目達成以下目標(biāo)。
提升產(chǎn)研效率
高功能復(fù)用度,提升開發(fā)效率。
降低研發(fā)人員(RD)、PM、QA之間的協(xié)作成本,提升產(chǎn)研協(xié)作的效率。
提升交付質(zhì)量
精確QA測試的范圍,提升交付的質(zhì)量。
對業(yè)務(wù)進行賦能。
PM可通過可視化的平臺化頁面,了解其他產(chǎn)品線的能力,互相賦能,助力產(chǎn)品迭代。
4 整體設(shè)計?
4.1 整體思想
目前,業(yè)界已經(jīng)有不少“平臺化”方向的研究,比如阿里巴巴的TMF,定位于泛交易類系統(tǒng)的平臺化領(lǐng)域范疇,主要建設(shè)思想是,流程編排與領(lǐng)域擴展分層,業(yè)務(wù)包與平臺分離的插件化架構(gòu),管理域與運行域分離。而阿里巴巴的AIOS則定位于搜推平臺化領(lǐng)域范疇,主要依賴于底層5大核心組件,以算子流程圖定制的模式對組件快速組合與部署,從而實現(xiàn)了業(yè)務(wù)的快速交付。美團外賣在平臺化項目啟動時,從業(yè)務(wù)場景和業(yè)務(wù)痛點出發(fā),確定了我們項目的核心目標(biāo):利用平臺化設(shè)計理念構(gòu)建相適應(yīng)的技術(shù)能力,將現(xiàn)有外賣廣告的業(yè)務(wù)系統(tǒng)和產(chǎn)研流程轉(zhuǎn)變?yōu)槠脚_化模式,快速支持外賣廣告多業(yè)務(wù)進行交付。我們借鑒了行業(yè)內(nèi)平臺化的成熟思想,確定了以業(yè)務(wù)能力標(biāo)準(zhǔn)化為基礎(chǔ)、構(gòu)建平臺化框架技術(shù)能力為支撐、產(chǎn)研平臺化模式升級為保障的平臺化建設(shè)整體思想,整體思想可分為三部分:業(yè)務(wù)能力標(biāo)準(zhǔn)化、技術(shù)能力框架化、平臺化產(chǎn)研新流程。 業(yè)務(wù)能力標(biāo)準(zhǔn)化:通過對現(xiàn)有邏輯的梳理,進行標(biāo)準(zhǔn)化的改造,為多業(yè)務(wù)場景、多模塊代碼復(fù)用提供基礎(chǔ)保證。 技術(shù)能力框架化:提供組合編排能力將標(biāo)準(zhǔn)化的邏輯串聯(lián)起來,通過引擎調(diào)度執(zhí)行,同時完成了可視化能力的透出,幫助用戶快速獲取信息。 平臺化產(chǎn)研新流程:為保證項目上線之后實現(xiàn)研發(fā)迭代的整體提效,我們對于研發(fā)流程的一些機制也進行了一些優(yōu)化,主要涉及研發(fā)人員、PM、QA三方。
即通過標(biāo)準(zhǔn)化提供復(fù)用的保證,通過框架承載平臺化落地的能力,通過產(chǎn)研新流程的運行機制保證了整體提效的持續(xù)性。整個廣告引擎服務(wù)涉及到的模塊都遵循了平臺化的思想,支撐上游各個產(chǎn)品場景,如下圖所示:

4.2 業(yè)務(wù)標(biāo)準(zhǔn)化
4.2.1 業(yè)務(wù)場景與流程分析
提效是平臺化最重要的目標(biāo)之一,而提效最重要的手段是讓功能在系統(tǒng)中得到最大程度上的復(fù)用。我們首先針對外賣廣告業(yè)務(wù)線場景和流量的現(xiàn)狀做了統(tǒng)一的分析,得出以下兩點結(jié)論:第一,各業(yè)務(wù)線大的流程基本類似,都包括預(yù)處理、召回、預(yù)估、機制策略、排序、創(chuàng)意、結(jié)果組裝等幾個大的步驟;同時,不同業(yè)務(wù)相同的步驟里會有很多相似的功能和業(yè)務(wù)線特有的功能。第二,這些功能理論上都是可以整體進行復(fù)用的,但現(xiàn)狀是這些功能都集中在業(yè)務(wù)線內(nèi)部,不同的業(yè)務(wù)線之間,不同的小組之間的復(fù)用狀況也不盡相同。而造成這一問題的主要原因是:
不同業(yè)務(wù)處在不同的發(fā)展階段,也有著不同的迭代節(jié)奏。
組織結(jié)構(gòu)天然存在“隔離”,如推薦和搜索業(yè)務(wù)分在兩個不同的業(yè)務(wù)小組。
因此,阻礙外賣廣告進一步提升復(fù)用程度的主要原因,在于整體的標(biāo)準(zhǔn)化程度不足,各業(yè)務(wù)線間沒有統(tǒng)一的標(biāo)準(zhǔn),所以我們要先解決標(biāo)準(zhǔn)化建設(shè)的問題。
4.2.2 標(biāo)準(zhǔn)化建設(shè)
標(biāo)準(zhǔn)化建設(shè)的廣度和深度決定了系統(tǒng)復(fù)用能力的高低。因此,本次標(biāo)準(zhǔn)化的建設(shè)目標(biāo)要覆蓋到所有方面。我們對廣告系統(tǒng)所有的服務(wù),從業(yè)務(wù)開發(fā)的三個維度,包括實現(xiàn)的功能、功能使用的數(shù)據(jù)、功能組合的流程出發(fā),來進行統(tǒng)一廣告的標(biāo)準(zhǔn)化建設(shè)。從而使得: 在個體開發(fā)層面:開發(fā)同學(xué)不用關(guān)注如何流程調(diào)度,只需將重心放在新功能的實現(xiàn)上,開發(fā)效率變得更高。 從系統(tǒng)整體角度:各個服務(wù)對于通用的功能不用再重復(fù)開發(fā),整體的復(fù)用程度更高,節(jié)省了大量的開發(fā)時間。?
4.2.2.1 功能的標(biāo)準(zhǔn)化?針對功能的標(biāo)準(zhǔn)化問題,我們首先依據(jù)功能是否跟業(yè)務(wù)邏輯相關(guān),將其劃分為兩部分:業(yè)務(wù)邏輯相關(guān)和業(yè)務(wù)邏輯無關(guān)。
① 與業(yè)務(wù)邏輯無關(guān)的功能通過雙層抽象來統(tǒng)一共建所有業(yè)務(wù)線統(tǒng)一共建的標(biāo)準(zhǔn)化形式是進行雙層抽象。對于單個的、簡單的功能點,抽象為工具層;對于可獨立實現(xiàn)并部署的某一方面功能,比如創(chuàng)意能力,抽象為組件層。工具層和組件層統(tǒng)一以JAR包的形式對外提供服務(wù),所有工程都通過引用統(tǒng)一的JAR包來使用相關(guān)的功能,避免重復(fù)的建設(shè),如下圖所示: 
② 與業(yè)務(wù)邏輯有關(guān)的功能,在復(fù)用范圍上進行分層復(fù)用 業(yè)務(wù)邏輯相關(guān)的功能是此次標(biāo)準(zhǔn)化建設(shè)的核心,目標(biāo)是做到最大程度的業(yè)務(wù)復(fù)用。因此,我們將最小不可拆分的業(yè)務(wù)邏輯單元抽象為業(yè)務(wù)同學(xué)開發(fā)的基本單位,稱為Action。同時根據(jù)Action不同的復(fù)用范圍,將其劃分為三層,分別是所有業(yè)務(wù)可以復(fù)用的基礎(chǔ)Action,多業(yè)務(wù)線復(fù)用的模塊Action,具體單一業(yè)務(wù)定制的業(yè)務(wù)Action,亦即擴展點。所有的Action都是從Base Action派生出來的,Base Action里定義了所有Action統(tǒng)一的基礎(chǔ)能力。
不同的Action類型分別由不同類型的開發(fā)同學(xué)來開發(fā)。對于影響范圍比較大的基礎(chǔ)Action和模塊Action,由工程經(jīng)驗豐富的同學(xué)來開發(fā);對于僅影響單個業(yè)務(wù)的業(yè)務(wù)Action或擴展點,由工程能力相對薄弱的同學(xué)來進行開發(fā)。
同時我們把多個Action的組合,抽象為Stage,它是不同Action組合形成的業(yè)務(wù)模塊,目的在于屏蔽細節(jié),簡化業(yè)務(wù)邏輯流程圖的復(fù)雜度,并提供更粗粒度的復(fù)用能力。
4.2.2.2 數(shù)據(jù)的標(biāo)準(zhǔn)化數(shù)據(jù)作為實現(xiàn)功能的基本元素,不同業(yè)務(wù)的數(shù)據(jù)來源大同小異。如果不對數(shù)據(jù)進行標(biāo)準(zhǔn)化設(shè)計,就無法實現(xiàn)功能標(biāo)準(zhǔn)化的落地,也無法實現(xiàn)數(shù)據(jù)層面的最大化復(fù)用。我們從數(shù)據(jù)來源和數(shù)據(jù)使用方式兩方面來劃分?jǐn)?shù)據(jù):對于業(yè)務(wù)能力的輸入數(shù)據(jù)、中間數(shù)據(jù),輸出數(shù)據(jù),通過標(biāo)準(zhǔn)化的數(shù)據(jù)上下文來實現(xiàn);同時對于第三方外部數(shù)據(jù)及詞表等內(nèi)部數(shù)據(jù),通過統(tǒng)一的容器存儲和接口獲取。① 使用上下文Context描述Action執(zhí)行的環(huán)境依賴
每個Action執(zhí)行都需要一定的環(huán)境依賴,這些依賴包括輸入依賴、配置依賴、環(huán)境參數(shù)、對其他Action的執(zhí)行狀態(tài)的依賴等。我們將前三類依賴都抽象到業(yè)務(wù)執(zhí)行上下文中,通過定義統(tǒng)一的格式和使用方式來約束Action的使用。
考慮不同層級Action對于數(shù)據(jù)依賴使用范圍由大到小,遵循相同的分層設(shè)計,我們設(shè)計了三層依次繼承的Context容器,并將三類依賴的數(shù)據(jù)標(biāo)準(zhǔn)化存儲到相應(yīng)的Context中。
使用標(biāo)準(zhǔn)化Context進行數(shù)據(jù)傳遞,優(yōu)勢在于Action可自定義獲取輸入數(shù)據(jù),以及后續(xù)擴展的便利性;同時標(biāo)準(zhǔn)化的Context也存在一定的劣勢,它無法從機制上完全限制Action的數(shù)據(jù)訪問權(quán)限,隨著后續(xù)迭代也可能導(dǎo)致Context日漸臃腫。綜合考慮利弊后,現(xiàn)階段我們?nèi)匀徊捎脴?biāo)準(zhǔn)的Context的模式。

② 第三方外部數(shù)據(jù)的統(tǒng)一處理對于第三方的外部數(shù)據(jù)的使用,需要成熟的工程經(jīng)驗提前評估調(diào)用量、負(fù)載、性能、批量或拆包等因素,所以針對所有第三方外部數(shù)據(jù),我們統(tǒng)一封裝為基礎(chǔ)Action,再由業(yè)務(wù)根據(jù)情況定制化使用。
③ 詞表數(shù)據(jù)的全生命周期管理詞表根據(jù)業(yè)務(wù)規(guī)則或策略生成,需要加載到內(nèi)存中使用的KV類數(shù)據(jù),標(biāo)準(zhǔn)化之前的詞表數(shù)據(jù)在生成、拉取、加載、內(nèi)存優(yōu)化、回滾、降級等能力上有不同程度的缺失。因此,我們設(shè)計了一套基于消息通知的詞表管理框架,實現(xiàn)了詞表的版本管理、定制加載、定時清理、流程監(jiān)控的全生命周期覆蓋,并定義了業(yè)務(wù)標(biāo)準(zhǔn)化的接入方式。?
4.2.2.3 調(diào)用流程的標(biāo)準(zhǔn)化最后,將功能和數(shù)據(jù)進行組合的是業(yè)務(wù)的調(diào)用流程,統(tǒng)一的流程設(shè)計模式是業(yè)務(wù)功能復(fù)用和提效的核心手段。流程設(shè)計統(tǒng)一的最佳方式就是標(biāo)準(zhǔn)化業(yè)務(wù)流程。其中對于第三方接口的調(diào)用方式,讓框架研發(fā)的同學(xué)用集中封裝的方式進行統(tǒng)一。對于接口的調(diào)用時機,則基于性能優(yōu)先并兼顧負(fù)載,且在沒有重復(fù)調(diào)用出現(xiàn)的原則下,進行標(biāo)準(zhǔn)化。在具體實踐中,我們首先梳理業(yè)務(wù)邏輯所使用到的標(biāo)準(zhǔn)化功能,然后分析這些功能之間的依賴關(guān)系,最后以性能優(yōu)先并兼顧負(fù)載、無重復(fù)調(diào)用等原則,完成整個業(yè)務(wù)邏輯流程的標(biāo)準(zhǔn)設(shè)計。
從橫向維度看,通過比較不同業(yè)務(wù)邏輯流程的相似性,我們也提煉了一定的實踐經(jīng)驗,以中控模塊為例:
對于用戶維度的第三方數(shù)據(jù),統(tǒng)一在初始化后進行封裝調(diào)用。
對于商家維度的第三方數(shù)據(jù),有批量接口使用的數(shù)據(jù),在召回后統(tǒng)一封裝調(diào)用;無批量接口使用的數(shù)據(jù),在精排截斷后統(tǒng)一封裝調(diào)用。?
4.3 技術(shù)框架
4.3.1 整體框架介紹
平臺主要有兩個部分組成,一部分是平臺前臺部分,另一部分是平臺開發(fā)框架包。其中前臺部分是一個給研發(fā)人員、PM以及QA三種角色使用的Web前臺,主要功能是跟集成了平臺開發(fā)框架包的引擎服務(wù)進行可視化的交互,我們也給這個平臺起了個名字,叫Camp平臺,這是大本營的意思,寓意助力業(yè)務(wù)方攀登業(yè)務(wù)高峰。平臺開發(fā)框架包被引擎后臺服務(wù)所集成,提供引擎調(diào)度隔離、能力沉淀、信息上報等功能,同時還能確保各個模塊保持同樣標(biāo)準(zhǔn)的框架和業(yè)務(wù)能力風(fēng)格。各個在線服務(wù)都需要引入平臺開發(fā)框架包,服務(wù)性能與平臺通用性之間如何平衡也是我們需要著重考慮的地方。這是因為,引入平臺框架會對原有的代碼細節(jié)進行增強性擴展;在C端大流量場景下,平臺框架做得越通用,底層功能做得越豐富,與單純的“裸寫”代碼相比,會帶來一些性能上的折損。因此,在性能開銷與平臺抽象能力上,需要盡量做到一個折中。我們結(jié)合自身業(yè)務(wù)的特性,給出的安全閾值是TP999損失在5ms以內(nèi),將各個業(yè)務(wù)通用的能力下沉至框架,提供給上層的在線服務(wù)。綜上,整個系統(tǒng)架構(gòu)設(shè)計如下:① Camp平臺提供管理控制和展示的功能,該平臺由以下幾個子模塊包組成:
業(yè)務(wù)可視化包,提供各個后臺系統(tǒng)上的能力的靜態(tài)信息,包括名稱、功能描述、配置信息等,這些信息在需求評估階段、業(yè)務(wù)開發(fā)階段都會被用到。
全圖化編排和下發(fā)包,業(yè)務(wù)開發(fā)同學(xué)通過對已有的能力進行可視化的拖拽,通過全圖化服務(wù)自動生成并行化最優(yōu)的執(zhí)行流程,再根據(jù)具體業(yè)務(wù)場景進行調(diào)整,最終生成一個有向無環(huán)圖,圖的節(jié)點代表業(yè)務(wù)能力,邊表示業(yè)務(wù)能力之間的依賴關(guān)系。該圖會動態(tài)下發(fā)到對應(yīng)的后臺服務(wù)去供執(zhí)行框架解析執(zhí)行。
統(tǒng)計監(jiān)控包,提供業(yè)務(wù)能力、詞典等運行期間的統(tǒng)計和異常信息,用于查看各個業(yè)務(wù)能力的性能情況以及異常情況,達到對各個業(yè)務(wù)能力運行狀態(tài)可感知的目的。
② 平臺開發(fā)框架包被廣告引擎的多個服務(wù)引入,執(zhí)行編排好的業(yè)務(wù)流程并對外提供服務(wù),平臺框架開發(fā)包由以下幾個子模塊包組成:
核心包,提供兩個功能,第一個是調(diào)度功能,執(zhí)行平臺下發(fā)的流程編排文件,按照定義的DAG執(zhí)行順序和執(zhí)行條件去依次或并行執(zhí)行各個業(yè)務(wù)能力,并提供必要的隔離和可靠的性能保證,同時監(jiān)控運行以及異常情況進行上報。第二個是業(yè)務(wù)采集和上報功能,掃描和采集系統(tǒng)內(nèi)的業(yè)務(wù)能力,并上報至平臺Web服務(wù),供業(yè)務(wù)編排以及業(yè)務(wù)能力可視化透出使用。
能力包,業(yè)務(wù)能力的集合,這里的業(yè)務(wù)能力在前面章節(jié)“4.2.2.1 功能的標(biāo)準(zhǔn)化”中已給出定義,即“將最小不可拆分的業(yè)務(wù)邏輯單元,抽象為業(yè)務(wù)同學(xué)開發(fā)的基本單位,稱為Action,也叫能力”。
組件包,即業(yè)務(wù)組件的集合,這里的業(yè)務(wù)組件在章節(jié)“4.2.2.1 功能的標(biāo)準(zhǔn)化”中也給出定義,即“對于可獨立實現(xiàn)并部署的某一方面功能,比如創(chuàng)意能力,抽象為組件”。
工具包,提供業(yè)務(wù)能力需要的基礎(chǔ)功能,例如引擎常用的詞典工具、實驗工具以及動態(tài)降級等工具。這里的工具在章節(jié)“4.2.2.1功能的標(biāo)準(zhǔn)化”中同樣給出了定義,即單個的、簡單的非業(yè)務(wù)功能模塊抽象為工具。

一個典型的開發(fā)流程如上圖所示 ,開發(fā)人員開發(fā)完業(yè)務(wù)能力后(1),業(yè)務(wù)能力的靜態(tài)信息會被采集到Camp平臺(2),同時,經(jīng)過全圖化依賴推導(dǎo)得到最優(yōu)DAG圖(3),業(yè)務(wù)同學(xué)再根據(jù)實際業(yè)務(wù)情況對DAG圖進行調(diào)整,引擎在線服務(wù)運行期間會得到最新的DAG流程并對外提供最新的業(yè)務(wù)流程服務(wù)(4,5),同時會把業(yè)務(wù)運行的動態(tài)信息上報至Camp平臺(6)。在下面的章節(jié)中,我們將對幾個比較關(guān)鍵的技術(shù)點進行詳細描述,其中就包括了可視化相關(guān)的組件自動上報和DAG執(zhí)行相關(guān)的全圖化編排、執(zhí)行調(diào)度等,最后,本文還會介紹一下跟廣告業(yè)務(wù)強相關(guān)的、詞典在平臺化中統(tǒng)一封裝的工作。
4.3.2 業(yè)務(wù)采集&上報
為了方便管理和查詢已有業(yè)務(wù)能力,平臺開發(fā)框架包會在編譯時掃描@LppAbility注解和@LppExtension注解來上報元數(shù)據(jù)到Camp平臺。業(yè)務(wù)同學(xué)可以在Camp平臺中對已有組件進行查詢和可視化的拖拽。//原子能力(Action)@LppAbility(name?=?"POI、Plan、Unit數(shù)據(jù)聚合平鋪能力",?desc?=?"做預(yù)算過濾之前,需要把對象打平",????????param?=?"AdFlatAction.Param",?response?=?"List<KvPoiInfoWrapper>",?prd?=?"無產(chǎn)品需求",?func?=?"POI、Plan、Unit數(shù)據(jù)聚合平鋪能力",?cost?=?1)public?abstract?class?AdFlatAction?extends?AbstractNotForceExecuteBaseAction?{}//擴展點@LppExtension(name?=?"數(shù)據(jù)聚合平鋪擴展點",????????func?=?"POI、Plan、Unit數(shù)據(jù)聚合平鋪",?diff?=?"默認(rèn)的擴展點,各業(yè)務(wù)線直接無差異",?prd?=?"無",?cost?=?3)public?class?FlatAction?extends?AdFlatAction?{@Override????protected?Object?process(AdFlatAction.Param?param)?{????//do?something??????return?new?Object();????}}

4.3.3 全圖化編排
在廣告投放引擎服務(wù)中,每個業(yè)務(wù)的DAG圖,動輒便會有幾十甚至上百的Action,通過傳統(tǒng)的人工編排或業(yè)務(wù)驅(qū)動編排,很難做到Action編排的最優(yōu)并行化。因此,平臺化框架包采用數(shù)據(jù)驅(qū)動的思想,通過Action之間的數(shù)據(jù)依賴關(guān)系,由程序自動推導(dǎo)出并行化最優(yōu)的DAG圖,即全圖化編排,此后再由業(yè)務(wù)人員根據(jù)業(yè)務(wù)場景和流量場景進行定制化調(diào)整,動態(tài)下發(fā)到服務(wù)節(jié)點,交由調(diào)度引擎執(zhí)行,這樣通過自動推導(dǎo)+場景調(diào)優(yōu)的方式便達到了場景下的最優(yōu)并行。
① 全圖化自動編排的基本原理我們定義某個Action x的入?yún)⒓蠟樵揂ction x執(zhí)行時使用的字段,表示如下:

定義某個Action y的出參集合為該Action執(zhí)行后產(chǎn)出的字段,表示如下:

當(dāng)存在任意以下兩種情況之一時,我們會認(rèn)為Action x依賴于Action y。
input_x ∩ output_y ≠ ?,即Action x的某個/某些入?yún)⑹怯葾ction y產(chǎn)出。
output_x ∩ output_y ≠ ?,即Action x與Action y操作相同字段。
② 全圖化自動編排總設(shè)計全圖化自動編排總體分為兩個模塊:解析模塊、依賴分析模塊。
解析模塊:通過對字節(jié)碼分析,解析出每個Action的input、output集合。
字節(jié)碼分析使用了開源工具ASM,通過模擬Java運行時棧,維護Java運行時局部變量表,解析出每個Action執(zhí)行依賴的字段和產(chǎn)出的字段。
依賴分析模塊:采用三色標(biāo)記的逆向解析法,分析出Action之間的依賴關(guān)系,并對生成的圖進行剪枝操作。
依賴剪枝:生成圖會有重復(fù)依賴的情況,為了減少圖復(fù)雜度,在不改變圖語義的前提下,對圖進行了依賴剪枝。例如:
③ 全圖化自動編排收益效果自動糾正人工錯誤編排,并最大化編排并行度。某實際業(yè)務(wù)場景中,全圖化前后的DAG對比,如下圖所示:

標(biāo)記藍色的兩個Action,會同時操作同一個Map,如果并發(fā)執(zhí)行會有線程安全風(fēng)險。由于方法調(diào)用棧過深,業(yè)務(wù)開發(fā)同學(xué)很難關(guān)注到該問題,導(dǎo)致錯誤的并行化編排。經(jīng)過全圖化分析后,編排為串行執(zhí)行。標(biāo)記綠色、紅色、黃色的三組Action,每組內(nèi)的兩個Action并沒有數(shù)據(jù)依賴關(guān)系,業(yè)務(wù)開發(fā)同學(xué)串行化編排。經(jīng)過全圖化分析后,編排為并行。4.3.4 調(diào)度引擎
調(diào)度引擎的核心功能是對上述下發(fā)后的DAG進行調(diào)度。因此引擎需要具備以下兩個功能:
構(gòu)圖:根據(jù)Action的編排配置生成具體的DAG模板圖。
調(diào)度:流量請求時,按照正確的依賴關(guān)系執(zhí)行Action。
整個調(diào)度引擎的工作原理如下圖:

出于對性能的考慮,調(diào)度引擎摒棄了流量請求實時構(gòu)圖的方法,而是采用“靜態(tài)構(gòu)圖+動態(tài)調(diào)度”的方式。
靜態(tài)構(gòu)圖:在服務(wù)啟動時,調(diào)度引擎根據(jù)下發(fā)的DAG編排配置,初始化為Graph模板并加載至內(nèi)存。服務(wù)啟動后,多個DAG的模板會持久化到內(nèi)存中。當(dāng)Web平臺進行圖的動態(tài)下發(fā)后,引擎會對最新的圖進行構(gòu)圖并完全熱替換。
動態(tài)調(diào)度:當(dāng)流量請求時,業(yè)務(wù)方指定對應(yīng)的DAG,連同上下文信息統(tǒng)一交至調(diào)度引擎;引擎按照Graph模板執(zhí)行,完成圖及節(jié)點的調(diào)度,并記錄下整個調(diào)度的過程。
由于廣告投放引擎服務(wù)于C端用戶,對服務(wù)的性能、可用性、擴展性要求很高。調(diào)度引擎的設(shè)計難點也落在了這三個方面,接下來我們將進行簡要的闡述。
4.3.4.1 高性能實踐流程引擎服務(wù)于C端服務(wù),與傳統(tǒng)的硬編碼調(diào)度相比,引擎的調(diào)度性能要至少能持平或在一個可接受的性能損失閾值內(nèi)。下面,我們將從調(diào)度器設(shè)計、調(diào)度線程調(diào)優(yōu)這兩個有代表性的方面介紹下我們的性能實踐。
① 調(diào)度器設(shè)計含義:如何讓節(jié)點一個一個的執(zhí)行;一個節(jié)點執(zhí)行完成,如何讓其他節(jié)點感知并開始執(zhí)行。如下圖中,A節(jié)點在執(zhí)行完成后,如何通知B,C節(jié)點并執(zhí)行。常見的思路是,節(jié)點的分層調(diào)度,它的含義及特點如下:
依賴分層算法(如廣度優(yōu)先遍歷)提前計算好每一層需要執(zhí)行的節(jié)點;節(jié)點一批一批的調(diào)度,無需任何通知和驅(qū)動機制。
在同批次多節(jié)點時,由于各節(jié)點執(zhí)行時間不同,容易出現(xiàn)長板效應(yīng)。
在多串行節(jié)點的圖調(diào)度時,有較好的性能優(yōu)勢。
另一種常見的思路是,基于流水線思想的隊列通知驅(qū)動模式:
某節(jié)點執(zhí)行完成后,立即發(fā)送信號給消息隊列;消費側(cè)在收到信號后,執(zhí)行后續(xù)節(jié)點。如上圖DAG中,B執(zhí)行完成后,D/E收到通知開始執(zhí)行,不需要關(guān)心C的狀態(tài)。
由于不關(guān)心兄弟節(jié)點的執(zhí)行狀態(tài),不會出現(xiàn)分層調(diào)度的長板效應(yīng)。
在多并行節(jié)點的圖調(diào)度時,有非常好的并行性能;但在多串行節(jié)點的圖中,由于額外存在線程切換和隊列通知開銷,性能會稍差。

如上圖所示,調(diào)度引擎目前支持這兩種調(diào)度模型。針對多串行節(jié)點的圖推薦使用分層調(diào)度器,針對多并行節(jié)點的圖推薦使用隊列流水線調(diào)度器。
分層調(diào)度器依賴于上面提到的分層算法,節(jié)點分批執(zhí)行,串行節(jié)點單線程執(zhí)行,并行節(jié)點池化執(zhí)行。
隊列流水線調(diào)度器無論是外層的圖任務(wù)(GraphTask)還是內(nèi)部節(jié)點任務(wù)(NodeTask)均采用池化的方式執(zhí)行。
節(jié)點調(diào)度機制
調(diào)度機制:消費側(cè)收到消息到節(jié)點被執(zhí)行,這中間的過程。如下DAG中,節(jié)點在接收到消息后需依次完成:檢驗DAG執(zhí)行狀態(tài)、校驗父節(jié)點狀態(tài)、檢驗節(jié)點執(zhí)行條件、修改執(zhí)行狀態(tài)、節(jié)點執(zhí)行這幾個過程,如下圖所示:

這幾個步驟的執(zhí)行,通常存在兩種方式:一種是集中式調(diào)度,由統(tǒng)一的方法進行處理;另一種是分散式調(diào)度,由每個后續(xù)節(jié)點獨自來完成。
我們采用的為集中式調(diào)度:某節(jié)點執(zhí)行完成后,發(fā)送消息到隊列;消費側(cè)存在任務(wù)分發(fā)器統(tǒng)一負(fù)責(zé)消費,再進行任務(wù)分發(fā)。
這樣做的出發(fā)點是:
如上圖中,ABC三個節(jié)點同時完成,到D節(jié)點真正執(zhí)行前仍有一系列操作,這個過程中如果不加鎖控制,D節(jié)點會出現(xiàn)執(zhí)行三次的情況;因此,需要加鎖來保證線程安全。而集中式任務(wù)分發(fā)器,采用無鎖化隊列設(shè)計,在保證線程安全的同時盡量規(guī)避加鎖帶來的性能開銷。
再如一父多子的情況,一些公共的操作(校驗圖/父節(jié)點狀態(tài)、異常檢測等),各子節(jié)點都會執(zhí)行一次,會帶來不必要的系統(tǒng)開銷。而集中式任務(wù)分發(fā)器,對公共操作統(tǒng)一進行處理,再對子節(jié)點任務(wù)進行分發(fā)。
分散式調(diào)度中,節(jié)點的職責(zé)范圍過廣,既需要執(zhí)行業(yè)務(wù)核心代碼,還需要額外處理消息的消費,職責(zé)非單一,可維護性較差。
因此,在項目實際開發(fā)中,考慮到實現(xiàn)的難度、可維護性、以及綜合考量性能等因素,最終采用集中式調(diào)度。
② 調(diào)度線程調(diào)優(yōu)調(diào)度引擎在DAG執(zhí)行上,提供了兩種API給調(diào)用方,分別為:
異步調(diào)用:GraphTask由線程池來執(zhí)行,并將最外層GraphTask的Future返回給業(yè)務(wù)方,業(yè)務(wù)方可以精準(zhǔn)的控制DAG的最大執(zhí)行時間。目前,外賣廣告中存在同一個請求中處理不同廣告業(yè)務(wù)的場景,業(yè)務(wù)方可以根據(jù)異步接口自由組合子圖的調(diào)度。
同步調(diào)用:與異步調(diào)用最大的不同是,同步調(diào)用會在圖執(zhí)行完成/圖執(zhí)行超時后,才會返回給調(diào)用方。
而底層調(diào)度器,目前提供上述講到兩種調(diào)度器。具體如下圖所示:

由此看出,調(diào)度引擎在內(nèi)部任務(wù)執(zhí)行上,多次用到了線程池。在CPU密集型的服務(wù)上,請求量過大或節(jié)點過多的話,大量線程切換勢必會影響到服務(wù)的整體性能。針對隊列通知調(diào)度器,我們做了一些調(diào)度優(yōu)化,盡量將性能拉回到?jīng)]有接入調(diào)度引擎之前。
調(diào)度線程模型調(diào)優(yōu) 針對同步調(diào)用的情況,由于主線程不會直接返回,而是在等待DAG圖執(zhí)行完成。調(diào)度引擎利用這一特點,讓主線程來執(zhí)行最外層的GraphTask,在處理每個請求時,會減少一次線程的切換。
串行節(jié)點執(zhí)行優(yōu)化 如上面DAG圖中,存在一些串行節(jié)點(如單向A→B→C→D),在執(zhí)行這4個串行節(jié)點時,調(diào)度引擎則不會進行線程的切換,而是由一個線程依次完成任務(wù)執(zhí)行。
在執(zhí)行串行節(jié)點時,調(diào)度引擎同樣不再進行隊列通知,而是采用串行調(diào)度的方式執(zhí)行,最大化減少系統(tǒng)開銷。
4.3.4.2 高可用實踐在高可用上,我們從隔離和監(jiān)控上簡要介紹下我們的實踐,它的核心原理如下圖所示:

① 業(yè)務(wù)隔離廣告場景中,同一服務(wù)中經(jīng)常會存在多條子業(yè)務(wù)線,每條業(yè)務(wù)線的邏輯對應(yīng)一張DAG。對于同一服務(wù)內(nèi)各個業(yè)務(wù)線的隔離,我們采用的是“單實例-多租戶”的方案。這是因為:
流程引擎活躍在同一個進程內(nèi),單實例方案管理起來要更容易。
流程引擎內(nèi)部實現(xiàn)過程中,針對圖的粒度上做了一些多租戶隔離工作,所以在對外提供上更傾向于單實例方案。
除DAG調(diào)度和Node調(diào)度為靜態(tài)代碼外,圖的存儲、DAG的選取與執(zhí)行、Node節(jié)點的選取與執(zhí)行、各DAG的節(jié)點通知隊列都采用多租戶隔離的思想。② 調(diào)度任務(wù)隔離調(diào)度任務(wù)主要分為:DAG任務(wù)(GraphTask)、節(jié)點任務(wù)(NodeTask)兩類。其中一個GraphTask對應(yīng)多個NodeTask,并且其執(zhí)行狀態(tài)依賴所有的NodeTask。調(diào)度引擎在執(zhí)行時,采用二級線程池隔離的方式將GraphTask和NodeTask的執(zhí)行進行隔離。這樣隔離的出發(fā)點是:
每個線程池職責(zé)單一,執(zhí)行任務(wù)更加單一,相應(yīng)的過程監(jiān)控與動態(tài)調(diào)整也更加方便。
如果共用一個線程池,如果出現(xiàn)瞬時QPS猛增,會導(dǎo)致線程池全被GraphTask占據(jù),無法提交NodeTask最終導(dǎo)致調(diào)度引擎死鎖。
因此,無論是線程精細化管理還是隔離性上,兩級線程池調(diào)度的方式都要優(yōu)于一級線程池調(diào)度。③ 過程監(jiān)控對DAG調(diào)度的監(jiān)控,我們將其分成三類。分別為異常、超時、統(tǒng)計,具體如下: 異常:圖/節(jié)點執(zhí)行異常,支持配置重試、自定義異常處理。 超時:圖/節(jié)點執(zhí)行超時,支持降級。 統(tǒng)計:圖/節(jié)點執(zhí)行次數(shù)&耗時,提供優(yōu)化數(shù)據(jù)報表。
? 4.3.4.3 高可用實踐廣告業(yè)務(wù)邏輯復(fù)雜,在投放鏈路上存在大量的實驗、分支判斷、條件執(zhí)行等。并且廣告投放服務(wù)的迭代頻率和發(fā)版頻率也非常高。因此,調(diào)度引擎在可擴展上首先要考慮的是如何調(diào)度條件節(jié)點,以及編排配置如何在無發(fā)布下快速生效這兩個問題。① 節(jié)點條件執(zhí)行對于節(jié)點的條件執(zhí)行,我們在配置DAG時,需要顯示的增加Condition表達式。調(diào)度引擎在執(zhí)行節(jié)點前,會動態(tài)計算表達式的值,只有滿足執(zhí)行條件,才會執(zhí)行該節(jié)點。② 配置動態(tài)下發(fā) 如前圖所示,我們將構(gòu)圖與調(diào)度通過中間態(tài)Graph模板進行解耦,編排配置可以通過Web平臺編輯后,動態(tài)下發(fā)到服務(wù)上。
由于調(diào)度引擎在調(diào)度過程中,多次用到了線程池,對于線程池的動態(tài)更新,我們借助了公司的通用組件對線程池進行動態(tài)化配置和監(jiān)控。?
4.3.4.4 調(diào)度引擎總結(jié)① 功能方面DAG核心調(diào)度 調(diào)度引擎提供兩種常見調(diào)度器的實現(xiàn),針對不同的業(yè)務(wù)場景,能較好的提供支持。
調(diào)度引擎采用經(jīng)典的兩級調(diào)度模型,DAG圖/節(jié)點任務(wù)調(diào)度更具有隔離性和可控性。 節(jié)點條件執(zhí)行對于節(jié)點的調(diào)度前置增加條件校驗功能,不滿足條件的節(jié)點不會執(zhí)行,調(diào)度引擎會根據(jù)上下文以及流量情況動態(tài)判斷節(jié)點的執(zhí)行條件。 超時處理對DAG、Stage、Node節(jié)點均支持超時處理,簡化內(nèi)部各個業(yè)務(wù)邏輯的超時控制,將主動權(quán)交給框架統(tǒng)一進行處理。在保證性能的前提之下,提高內(nèi)部邏輯的處理效率。 節(jié)點可配置化同一個Node節(jié)點,會被對個業(yè)務(wù)場景使用,但各業(yè)務(wù)場景的其處理邏輯且不近相同。針對這種情況,增加節(jié)點的配置化功能,框架將節(jié)點的配置傳入邏輯內(nèi)部,實現(xiàn)可配置。 ② 性能方面 在多串行節(jié)點的DAG場景下,性能基本可以持平原有的裸寫方式。
在多并行節(jié)點的DAG場景下,由于池化的影響,在多線程池?fù)屨己颓袚Q上,存在一些性能折損;再進行多次調(diào)優(yōu)和CPU熱點治理上,TP999折損值可以控制到5ms以內(nèi)。
4.3.5 業(yè)務(wù)組件層沉淀
如“4.2.2.1 功能的標(biāo)準(zhǔn)化”中給出的定義,可獨立實現(xiàn)并部署的業(yè)務(wù)功能模塊抽象為業(yè)務(wù)組件。從業(yè)務(wù)邏輯中提取高內(nèi)聚、低耦合的業(yè)務(wù)組件,是提升代碼復(fù)用能力的重要手段。在實踐中,我們發(fā)現(xiàn)不同業(yè)務(wù)組件包含的邏輯千差萬別,具體實現(xiàn)方式和設(shè)計與代碼風(fēng)格也參差不齊。因此,為了統(tǒng)一業(yè)務(wù)組件的設(shè)計思路和實現(xiàn)方式,我們實現(xiàn)了一套標(biāo)準(zhǔn)化的組件框架,以減少新組件開發(fā)的重復(fù)性工作,并降低使用方的學(xué)習(xí)和接入成本。

上圖左邊展示了業(yè)務(wù)組件的整體框架,底層為統(tǒng)一的公共域和公共依賴,上層為業(yè)務(wù)組件標(biāo)準(zhǔn)的實現(xiàn)流程,切面能力則實現(xiàn)對業(yè)務(wù)邏輯的支持。右邊為基于框架開發(fā)的智能出價組件示例。
框架的作用是:① 統(tǒng)一的公共域和依賴管理 公共域是指在不同的業(yè)務(wù)組件中都會使用到的業(yè)務(wù)實體。我們將業(yè)務(wù)上的公用域?qū)ο筇崛〕鰜恚鳛榛A(chǔ)組件提供給其他業(yè)務(wù)組件使用,以減少域?qū)ο笤诓煌M件重復(fù)定義。
業(yè)務(wù)組件都有很多內(nèi)部和外部的依賴。我們對公共依賴進行了統(tǒng)一的梳理和篩選,同時權(quán)衡各方面因素,確定了合理的使用方式。最終形成一套完整成熟的依賴框架。
② 統(tǒng)一的接口和流程我們將業(yè)務(wù)組件抽象為三個階段:數(shù)據(jù)和環(huán)境準(zhǔn)備階段Prepare、實際計算階段Process和后置處理階段Post。每個階段都設(shè)計了抽象的泛型模板接口,最后通過不同的接口組合完成組件中的不同業(yè)務(wù)流程。所有類在接口設(shè)計上都提供了同步和異步兩種調(diào)用方式。
③ 統(tǒng)一的切面能力目前所有的服務(wù)模塊均采用Spring作為開發(fā)框架,我們利用其AOP功能開發(fā)了一系列的切面擴展能力,包括日志采集、耗時監(jiān)控、降級限流、數(shù)據(jù)緩存等功能。這些功能均采用無侵入式代碼設(shè)計,減少切面能力與業(yè)務(wù)邏輯的耦合。新的業(yè)務(wù)組件通過配置的方式即可完全復(fù)用。
智能出價組件即為基于以上框架開發(fā)的業(yè)務(wù)組件。智能出價組件是對廣告出價策略的抽象聚合,包括PID、CEM等多個算法。出價策略依賴的用戶特征獲取、實驗信息解析等數(shù)據(jù)統(tǒng)一采用Prepare模板實現(xiàn);具體PID、CEM算法的實施統(tǒng)一采用Process模板實現(xiàn);對出價結(jié)果的校驗、參數(shù)監(jiān)控等后置操作則統(tǒng)一采用Post模板實現(xiàn)。整個組件所使用的公用域?qū)ο蠛偷谌揭蕾囈步y(tǒng)一托管于框架進行管理。4.3.6 工具包-詞典管理
在“4.2.2.1 功能的標(biāo)準(zhǔn)化”中也定義了工具包的含義,即單個的、簡單的非業(yè)務(wù)功能模塊抽象為工具。工具包的建設(shè)是廣告平臺化工作提效的重要基礎(chǔ),其主要的作用是處理業(yè)務(wù)邏輯無關(guān)的輔助類通用流程或功能。例如:廣告系統(tǒng)中存在大量的KV類數(shù)據(jù)需要加載到內(nèi)存中使用,我們稱之為詞表文件。為了實現(xiàn)詞表文件的全生命周期管理,廣告平臺化進行了詞表管理工具的設(shè)計與開發(fā),并在業(yè)務(wù)使用過程中積累了很好的實踐效果。
① 詞表管理的設(shè)計

上圖是詞表管理平臺的整體架構(gòu),詞表管理平臺整體采用分層設(shè)計,自上而下分別五層:
存儲層:主要用于數(shù)據(jù)的存儲和流轉(zhuǎn)。其中美團內(nèi)部的S3完成在云端的詞表文件存儲,Zookeeper主要用于存儲詞表的版本信息,在線服務(wù)通過監(jiān)聽的方式獲取最新的版本更新事件。
組件層:每個組件可以視為獨立的功能單元,為上層提供通用的接口。
插件層:業(yè)務(wù)插件的作用主要是提供統(tǒng)一的插件定義和靈活的自定義實現(xiàn)。例如:加載器主要用途為提供統(tǒng)一格式的詞表加載和存儲功能,每個詞表可以動態(tài)配置其加載器類型。
模塊層:模塊層主要是從業(yè)務(wù)角度看整體詞表文件不同流程的某一環(huán)節(jié),模塊之間通過事件通知機制完成交互。例如:詞表管理類模塊包含詞表版本管理、事件監(jiān)聽、詞表注冊、詞表加/卸載、詞表訪問等。
流程層:我們將一個完整詞表業(yè)務(wù)行為過程定義為流程。詞表的整個生命周期可以分為新增詞表流程、更新詞表流程、注銷詞表流程、回滾詞表流程等。
② 詞表管理的業(yè)務(wù)收益平臺化詞典管理工具在業(yè)務(wù)實踐中具有的主要優(yōu)勢為:
更靈活的服務(wù)架構(gòu):詞表流程的透明化。使用方無需關(guān)注詞表流轉(zhuǎn)過程,采用統(tǒng)一API訪問。
統(tǒng)一的業(yè)務(wù)能力:統(tǒng)一的版本管理機制,統(tǒng)一的存儲框架,統(tǒng)一的詞表格式和加載器。
系統(tǒng)高可用:快速恢復(fù)和降級能力,資源和任務(wù)隔離、多優(yōu)先級處理能力等多重系統(tǒng)保障功能。
4.4 產(chǎn)研新流程
上文中提到,由于廣告業(yè)務(wù)線較多,且涉及諸多上下游,工程與策略經(jīng)過幾年快速迭代之后,現(xiàn)有業(yè)務(wù)邏輯已極為復(fù)雜,導(dǎo)致在日常迭代中,一些流程性問題也逐步凸顯。
① PM信息獲取困難PM在進行產(chǎn)品調(diào)研與設(shè)計時,對涉及的相關(guān)模塊當(dāng)前邏輯不是很清楚,往往通過線下咨詢研發(fā)人員的方式來解決,影響雙方的效率,同時產(chǎn)品設(shè)計文檔中純以業(yè)務(wù)視角和流程來闡述,導(dǎo)致每次評審時,QA和研發(fā)人員很難直觀獲取到改動點和改動范圍,中間又會花費大量時間來相互溝通,從而確認(rèn)邊界與現(xiàn)有邏輯的兼容性等問題。
② 研發(fā)人員的功能評估完全依賴經(jīng)驗研發(fā)人員在方案設(shè)計時,很難直接獲取到橫向相關(guān)模塊是否有類似功能點(可復(fù)用或可擴展),導(dǎo)致復(fù)用率低,同時在項目排期時完全依賴個人經(jīng)驗,且沒有統(tǒng)一的參考標(biāo)準(zhǔn),經(jīng)常出現(xiàn)因工作量評估不準(zhǔn)而導(dǎo)致項目延期的情況。
③ QA測試及評估效率低QA在功能范圍評估時,完全依賴研發(fā)同學(xué)(RD)的技術(shù)方案,且大多數(shù)也是通過口頭交流的方式來確認(rèn)功能改動涉及的范圍和邊界,在影響效率的同時,還會導(dǎo)致一些測試問題在整個項目周期中被后置,影響項目的進度。同時,平臺化后基礎(chǔ)JAR包的管理完全依靠人工,對一些Action,尤其是基礎(chǔ)Action也沒有統(tǒng)一的測試標(biāo)準(zhǔn)。以上問題可以概括如下:

4.4.1 目標(biāo)
借助平臺化,對項目交付的整個過程(如下圖所示),實施產(chǎn)研新流程,以解決產(chǎn)品、研發(fā)與測試人員在迭代中遇到的問題,賦能業(yè)務(wù),從而提升整體項目的交付效率與交付質(zhì)量。

4.4.2 思考與落地
基于平臺化實施產(chǎn)研新流程,即利用Stage/Action的方式來驅(qū)動整個項目的交付,如下圖所示:

對于PM(產(chǎn)品):建設(shè)Stage/Action可視化能力,并在項目設(shè)計中應(yīng)用。
對于RD(研發(fā)):統(tǒng)一采用新的基于Stage/Action的方案,設(shè)計及開發(fā)排期模式。
對于QA(測試):統(tǒng)一溝通協(xié)作語言-Stage/Action,并推動改進相關(guān)測試方法和測試工具
4.4.2.1 產(chǎn)品側(cè)下圖所示的是產(chǎn)研功能建設(shè)后的應(yīng)用與實踐效果。前兩張為建設(shè)的業(yè)務(wù)能力可視化,為PM提供一個了解各業(yè)務(wù)最新流程及詳細Action能力的可視化功能,第三張圖為產(chǎn)品設(shè)計中相關(guān)業(yè)務(wù)的調(diào)研與功能描述(出于數(shù)據(jù)安全原因,以下截圖采用非真實項目舉例說明)。

業(yè)務(wù)流程

業(yè)務(wù)功能詳情

產(chǎn)品設(shè)計中部分調(diào)研信息與功能描述
4.4.2.2 研發(fā)側(cè)根據(jù)項目開發(fā)周期中研發(fā)工作的不同階段,我們制定了基于代碼開發(fā)前后的流程規(guī)范,以保證整個開發(fā)周期中研發(fā)同學(xué)能充分利用平臺的能力進行設(shè)計與開發(fā)提效。
開發(fā)前
技術(shù)設(shè)計:基于各業(yè)務(wù)涉及的現(xiàn)有Action功能與Action DAG的可視化能力,進行橫向業(yè)務(wù)的調(diào)研參考與復(fù)用評估,以及新增或變更Action功能的技術(shù)設(shè)計。
項目排期:基于技術(shù)設(shè)計中Action能力的新增、變更、復(fù)用情況以及Action層級等,對開發(fā)工作量進行較為標(biāo)準(zhǔn)化的評估。
開發(fā)后
Action沉淀:系統(tǒng)統(tǒng)一上報并定期評估平臺Action能力的復(fù)用度和擴展情況。
流程反饋:追蹤基于平臺化的每個項目,并對交付流程中的相關(guān)指標(biāo)做量化上報,同時收集項目人員反饋。
? 4.4.2.3 測試側(cè)采用Stage/Action統(tǒng)一溝通協(xié)作語言:在需求設(shè)計與評審、方案設(shè)計與評審、測試用例編寫與評審等多方參與的項目環(huán)節(jié),統(tǒng)一采用Stage/Action為功能描述與設(shè)計的溝通語言,以便將后續(xù)流程中問題的發(fā)現(xiàn)盡可能前置,同時各參與方更加明確變更及測試內(nèi)容,為QA更好的評估測試范圍提供支撐,進而更好的保證項目測試質(zhì)量。
推動基礎(chǔ)Aaction UT全覆蓋:針對基礎(chǔ)Action,構(gòu)建單元測試,在Merge代碼時自動觸發(fā)單元測試流水線,輸出執(zhí)行單測的成功率和覆蓋率,并評定指標(biāo)基線,保證可持續(xù)測試的效率與質(zhì)量。
改進JAR管理工具化與自動化分析及測試:一級Action都集中寫在平臺JAR包中,對類似這種公共JAR包的管理,開發(fā)專屬的管理與維護工具,解決升級公共JAR自動化單測覆蓋問題以及每次升級JAR版本需要人工分析人工維護的測試效率問題,打通集成測試自動化的全流程。
5 效果?
① 產(chǎn)研效率的提升
系統(tǒng)能力沉淀
外賣廣告所有業(yè)務(wù)線已經(jīng)完成平臺化架構(gòu)升級,并在此架構(gòu)上持續(xù)的運行和迭代。
業(yè)務(wù)基礎(chǔ)能力沉淀50+個,模塊共用能力沉淀140+個,產(chǎn)品線共用能力沉淀500+個。
人效的提升
研發(fā)效率提升:在各業(yè)務(wù)線平臺化架構(gòu)遷移后,大的業(yè)務(wù)迭代20+次,業(yè)務(wù)迭代效率提升相比之前總計提升28+%。特別是在新業(yè)務(wù)的接入上,相同功能無需重復(fù)開發(fā),提效效果更加明顯:能力累計復(fù)用500+次,能力復(fù)用比52+%;在新業(yè)務(wù)接入場景中,Action復(fù)用65+%。
測試的自動化指標(biāo)提升:借助于JAR自動化分析、集成測試及流程覆蓋建設(shè),廣告自動化測試覆蓋率提升了15%,測試提效累計提升28%,自動化綜合得分也有了明顯提升。 ② 提升交付質(zhì)量及賦能產(chǎn)品 基于Action的變更以及清晰的可視化業(yè)務(wù)鏈路,能夠幫助QA更準(zhǔn)確的評估影響范圍,其中過程問題數(shù)量及線上問題數(shù)量均呈下降趨勢,下降比例約為10%。
通過系統(tǒng)能力的可視化透出頁面,增加系統(tǒng)的透明度,在產(chǎn)品調(diào)研階段有效幫助產(chǎn)品了解系統(tǒng)已有的能力,減少了業(yè)務(wù)咨詢、跨產(chǎn)品線知識壁壘等問題(詳情可參見4.4.2.1)。?
6 總結(jié)與展望
本文分別從標(biāo)準(zhǔn)化、框架、產(chǎn)研新流程3個方面介紹了外賣廣告平臺化在建設(shè)與實踐中的思考與落地方案。經(jīng)過兩年的摸索建設(shè)和實踐,美團外賣廣告平臺化已經(jīng)初具規(guī)模、有力地支撐了多條業(yè)務(wù)線的快速迭代。未來,平臺化會細化標(biāo)準(zhǔn)化的力度,降低業(yè)務(wù)開發(fā)同學(xué)成本;深化框架能力,在穩(wěn)定性、性能、易用性方面持續(xù)進行提升。此外,我們在產(chǎn)研新流程方向也會持續(xù)優(yōu)化用戶體驗,完善運營機制,不斷提升產(chǎn)研迭代的流程。以上就是外賣廣告針對業(yè)務(wù)平臺化上的一些探索和實踐,在廣告工程架構(gòu)等其他領(lǐng)域的探索,敬請期待下一篇系列文章。
(部分內(nèi)容來源網(wǎng)絡(luò),如有侵權(quán)請聯(lián)系刪除)