Twitter廣告之“道”,twitter有哪些廣告位Twitter廣告之“道”譯者的話我是酥酥,目前在Tubi用Akka和Scala搭建AdServer,此前在Twitter做廣告API的開發。我在從經濟系畢業生到硅谷程序員一文中提到,在我離開Twitter前,Twitter的廣告平臺組剛開始風風火火地對AdServ......
譯者的話
我是酥酥,目前在Tubi用Akka和Scala搭建AdServer,此前在Twitter做廣告API的開發。我在從經濟系畢業生到硅谷程序員一文中提到,在我離開Twitter前,Twitter的廣告平臺組剛開始風風火火地對AdServer進行微服務化重構,項目名稱Project Tao(道)。如今一年多過去,Twitter完成了廣告平臺的重構,并用博文Accelerating ad product development at Twitter記錄了這一過程,對從事AdServer工作的我很有啟發。我根據自己有限的知識,對全文進行了翻譯,并在局部進行了重寫。
康威定律指出,組織的架構決定系統的架構。Twitter廣告團隊也不例外。2010年,廣告團隊有約15名工程師和2800萬美元的收入,到了2019年,團隊增長至數百名工程師,有約34億美元的收入。期間,Twitter廣告系統的功能和復雜性一直在增加,而團隊或服務的運營模式并沒有大幅改變。
團隊早期的系統架構很適合初創公司,有利于拋下之前的決策包袱,快速迭代。廣告后端大致分為三個團隊。平臺(Platform)、科學(Science)和產品(Product)。團隊的最終目標是:快速構建和迭代廣告產品,幫助Twitter實現盈利。
Twitter的廣告平臺由基礎設施和核心組件構成,其中核心組件又包括AdServer、計費(billing)、數據基礎設施、分析(analytics)等系統。其中,單體AdServer(Monolithic AdServer)是廣告平臺的核心服務。它從Twitter客戶端獲取廣告請求,根據用戶信息和廣告主的定向(targeting)條件,對廣告池里的候選廣告進行排名,篩選出最符合條件的廣告,然后進行次價拍賣(second price auction),最后為用戶發快遞最相關的廣告作為響應。
團隊分工方面,平臺團隊負責搭建可靠、高性能的單體AdServer,并承擔部署和oncall的責任。產品團隊的重點則是根據Twitter前端產品團隊提的需求,在AdServer上做改動。本質上,平臺團隊扮演一個把關的角色,對改動和服務進行全面的控制。產品團隊則在平臺團隊的把關下,在代碼庫的各處做改動。
基于這種模式,Twitter打造了多款成功的廣告產品,它們的目標各不相同,復雜度越來越高。Promoted Tweets(推廣推文)首先推出,它幫助品牌覆蓋廣大的受眾,以提高品牌產品的知名度。Promoted Trend(推廣趨勢,類似于微博熱搜)使得品牌能夠占用全部Twitter用戶的探索欄全天的時間。Mobile App Promotion(移動app推廣)鼓勵用戶下載廣告主所要推廣的手機app。Web Clicks(網頁點擊)鼓勵用戶訪問品牌網站。Promoted Video(推廣視頻)讓品牌通過視頻這種更容易講故事的媒介來做推廣,還支持對廣告覆蓋面和效果的衡量。
這種模式在小規模的工程師團隊中效果非常好,迭代速度很快。但隨著業務和團隊的增長,平臺團隊開始成為功能迭代的瓶頸。為了更好地說明這一點,下面首先概述一個廣告請求的流程。
廣告請求的工作流
為了提供最相關的廣告,我們在廣告請求路徑中使用以下兩個組件:Ad Mixer和單體AdServer。
Ad Mixer是ad serving管道的網關(gateway)服務。每當收到一個來自客戶端的廣告請求,它都會:
·將請求轉發給單體AdServer,并接收來自AdServer的候選廣告響應。
·執行次價拍賣,根據拍賣結果決定將要展示的廣告。
·儲存被展示的廣告的信息,根據用戶與廣告的交互行為,向廣告商收費。(譯者注:例如,如果用戶瀏覽了廣告,Twitter向廣告商收取x元。如果用戶瀏覽并下載了被推廣的app,Twitter可能向廣告商收取x+y元。)
單體AdServer負責對于每一個請求,考慮每一個符合條件的廣告,并將最佳的候選廣告返回給AdMixer。考慮到Twitter廣告產品的規模,該服務是分片(sharded)的,這樣每個分片只考慮全部候選廣告的一個子集。這種分片方案還使并行計算成為可能,滿足對廣告請求延遲的嚴格要求(要求在200500毫秒不等)。
譯者注:拆分前,廣告請求的工作流。
譯者注:在此需要簡單了解廣告的三級結構:廣告組/campaign廣告計劃/line item廣告創意/creative。一個廣告組對應一到多個廣告計劃,一個廣告計劃對應一到多個廣告創意。廣告組描述一次推廣,例如“Nike瑜伽裝備2020秋季推廣”。廣告計劃通常包含對目標群體的描述,如“男性推廣”、“女性推廣”和“兒童推廣”,分別對應于三個目標群體。廣告創意描述具體要展示的內容,可能是一段視頻、一張海報、或一段文字。
每個AdServer分片,都根據它的候選廣告子集,執行以下步驟。
·候選廣告選擇。我們為用戶剔除不相關(不符合年齡、地區或興趣等)的廣告,篩選出符合條件的廣告計劃。(譯者注:例如,若請求來自一個女性用戶,則篩除有關“男性推廣”的廣告計劃。)
·廣告創意的擴展和產品邏輯。我們根據Twitter的產品規則(因產品種類而異),將每一個候選廣告計劃擴展為一組廣告創意,并根據產品規則作進一步的過濾。(譯者注:將候選廣告擴展為廣告創意的過程可能涉及實時競價,即Realtime bidding,指AdServer根據廣告計劃的定向信息和用戶信息,對廣告交易所等第三方進行競價請求,從第三方獲取動態報價及創意信息。)
·候選廣告排名(包括早期過濾)。我們在產品邏輯階段后,根據用戶點擊廣告的可能性(調用實時訓練的機器學習模型)、廣告商的競價信息和拍賣特征,對候選廣告進行評分和排名。
從2010年到2018年,AdServer的邏輯日漸復雜。結果是:
·每次部署有包含數百個改動;(譯者注:Twitter出于各項考慮,沒有使用持續部署的方式,因此一次部署包含很多改動)
·雖然平臺團隊管理著AdServer,但AdServer的主要改動卻是來自產品團隊,導致兩個團隊“互為掣肘”。
此外,AdServer的幾個步驟之間沒有劃定明確的邊界,缺乏有效的機制來確保屬于廣告創意的擴展和產品邏輯的代碼不被加入到候選廣告選擇或候選廣告排名中。不清晰的邊界還給產品團隊的工程師(譯者注:以下簡稱產品工程師)帶來了額外的復雜性:單體AdServer本就是一個黑盒子,組件間強耦合,缺了哪一塊,AdServer都無法正常工作。產品工程師只了解AdServer的局部,很難測試。有時,一個很簡單的改動從開始開發到部署至生產中需要一個月的時間。
譯者注:單體AdServer的邏輯復雜。
廣告產品功能的生命周期
在2018年,基于上述平臺團隊和產品團隊的結構,一個視頻廣告產品功能的生命周期如下:
代碼考古
由于產品和平臺的耦合,業務邏輯和基礎架構組件之間缺乏清晰的API邊界,AdServer代碼的復雜度指數爆炸。產品工程師首先需要理解錯綜復雜的平臺組件和產品組件,并試圖弄清楚當前AdServer是怎樣工作的。
設計
隨后,產品工程師將明確:需要對系統進行哪些改動這里的挑戰包括:產品工程師難以完全理解視頻產品的改動對運行在同一單片AdServer中的其他廣告產品的影響。此外,他們也很難估計改動對性能的影響。
咨詢平臺團隊
一旦設計準備就緒,產品團隊的下一步將是與平臺團隊對接,由平臺團隊負責提供指導和代碼審查。然而現實中,由于平臺團隊負責平臺,而產品團隊負責產品,兩個團隊的激勵并不總是一致的,這導致產品的很多請求被平臺爭論甚至駁回,兩個團隊都感到失望和沮喪。
發布
一旦代碼通過審查,被合并,產品團隊需要再次依靠平臺團隊進行部署。新功能的測試往往十分困難,有時一個部署要包括多達200個改動。此外,由于多個產品的邏輯運行在同一個強耦合的單體AdServer中,一個錯誤的改動可能阻塞整個部署,從而影響到其它產品團隊。最終的測試要到發布后才能完成,且需要不同團隊的參與,因此修復突發bug的時間難以預測。
解決方案
引入產品競價器,加速產品迭代
我們從多個方面解決這些問題。我們首先將服務于不同廣告產品的基礎設施組件分離出來(例如選擇服務Selection Service,排名服務Ranking Service等,更多信息見我們之前的博文)。此外,提高產品團隊迭代速度的關鍵在于引入產品競價器(Product Bidder),并確保不同產品的競價器共用一個框架,以保持乘法效應。(譯者注:將拆分后的AdServer命名為bidder,可能因為競價是AdServer的一個重要環節,不同產品之間的競價邏輯可能差異較大。)
譯者注:拆分后,廣告請求的工作流。
將單體服務的每個模塊都拆分為一個微服務看似會大大提高產品迭代效率,但這也使得跨服務改動經常發生,降低開發效率。因此,在拆分過程中,我們做了適當的取舍:
1.將單體AdServer拆分成不同的產品競價器服務,負責返回每個產品品種的最佳廣告。例如,視頻競價器只負責返回最佳的視頻廣告,手機app推廣競價器只負責返回最好的手機app推廣廣告。因此,每個競價器可以有自己的部署節奏、oncall、性能和運營特點。
2.將AdServer代碼庫拆分成競價器框架和產品專用邏輯,每個競價器的實現是競價器框架和產品邏輯的可配置組合。
譯者注:拆分后的AdServer流水線。
競價器框架
如上圖所示,每個管道(pipeline)都包含Filter和Enricher等多個步驟。競價器框架規定了這條流水線的結構和執行機制,而每個產品競價器可以根據具體產品需求做定制化執行。
這種方法解耦了服務與產品,從而使平臺團隊只負責競價器框架,產品團隊負責競價器的具體實現。它最大程度地提高了開發的敏捷性和速度,同時保留了乘數效應。例如,框架升級會同時作用于所有產品競價器;所有產品競價器還能共享一套分析數據采集機制。
不同產品競價器之間的相互獨立,使得工程師可以對特定產品(如視頻廣告)進行更改,而完全不影響與視頻廣告不相關的產品。例如,如果一個新的視頻功能需要額外的計算資源,視頻產品競價器可以增大其允許延時,而不改變其它廣告產品的行為。
數據依賴框架
(譯者注:本段大量根據自己的理解寫成,可能與原文有出入)在AdServer的整條流水線中,每個步驟都涉及對通用數據結構的直接改動,這使得我們很難找出數據具體是在哪一個步驟被修改的。我們開發了一套數據依賴框架,嚴格規定了每個步驟的輸入輸出格式,禁止對通用數據結構的直接改動,而需要通過immutable的方式做改動,這樣能使每個步驟的職責更為清晰。
分片服務的數據獲取與傳輸
譯者注:在Ad Mixer處進行數據抓取。
在原有系統中,Ad Mixer在每次廣告請求中,都會一次性獲取所需數據(比如用戶的個人信息、興趣、活動等),并將數據傳遞給各個分片AdServer。在拆分后,每個競價器需要不同的數據源,然而我們希望避免每個拆分的服務都各自進行數據獲取,因為這可能會使數據的獲取量增加400倍。我們選擇仍然在Ad Mixer處做一次性數據獲取,并使用以下方法確保競價器高效地獲取各自所需數據:
1.對于不需要類型檢查的數據,我們實現了直通(passthrough),中間服務只負責將原始字節傳輸到指定的下游服務,而不需要知道數據的格式和內容。(譯者注:直通避免了序列化,降低數據傳輸成本。)
2.對于需要進行類型檢查的數據,我們對其進行分類,并標記它們的消費者,以避免泄漏封裝,并確保下游服務不會錯誤地使用數據。(譯者注:若將某數據的消費者標記為視頻廣告競價器,則手機app推廣廣告競價器的邏輯將不會消費該數據。)
挑戰與經驗
可靠的逐步遷移
在我們進行拆分之前,Twitter的單體AdServer上運行著價值30億美元的廣告業務。因此,在做拆分的同時,我們必須保持現有業務的運行,以及支持正在進行的產品開發。
在項目過程中,我們進行了廣泛的A/B實驗,由新系統支持小部分流量,由原有系統支持大部分流量,對產品指標進行詳盡分析,確保兩個系統在收入和各項指標上都基本符合,希望在不影響正常廣告業務的前提下,及早發現問題。
我們在長達4周的時間內,逐漸地給新系統增加流量比例。此外,我們還為每個產品競價器部署了約20%額外的容量,并啟用了保證30秒內完成回滾的機制。最后,我們在長達一個季度的時間內,將小比例的流量運行在之前的單體AdServer上,用于研究季節性對各項指標的影響。
代碼復雜度
拆分無可避免地需要直面非常復雜的遠古代碼,我們要搞清楚這些好幾年沒人碰過的代碼到底在做什么。我們努力將數據處理邏輯歸類到“候選廣告選擇”、“候選廣告排名”等核心組件,或是“預算計算”、“頻率管理”等小組件中。在技術債的泥潭中,做這些改動并不簡單。
揭露潛藏的bug
過去的八年中,團隊一直對AdServer做漸進性的改動,這樣做的缺點是難以發現大bug。這次拆分對系統做根本性的改變,幫我們發現了軟件中潛藏的bug。發現、診斷并修復這些bug花了我們一個季度的時間,但這使我們的系統更為健康。
權衡取舍
任何解決方案都不是萬能的,我們的團隊充分認識到這個決定的風險和收益,做出以下的“舍”:
失去對候選廣告做全局排名的能力
當我們將單體AdServer垂直拆分為多個產品競價器時,每個產品競價器都會分別給候選廣告排名。從而,我們失去了在AdServe內以接近全局的方式對所有候選廣告進行排名的能力。我們清楚利弊,決定通過增加最終拍賣所考慮的候選廣告的數量來彌補局部決策帶來的損失,以確保我們不會過濾掉原本有資格的候選廣告。(譯者注:假設有兩種廣告產品,視頻廣告和卡片廣告,二者分別有10個候選廣告。假定全局最優的5個廣告中,有4個視頻廣告和1個卡片廣告。那么,如果我們在局部排名中,分別對視頻廣告和卡片廣告取前3名,匯總后再進行全局排名,則我們錯誤地過濾掉了一條視頻廣告。Twitter可能通過對二者各取前5名的方式來減少這種情況的發生。)
下游服務的流量增大
考慮到AdServer的規模,我們必選在項目開始時就估計好服務的流量情況,并提前6個月告知基礎設施團隊。我們使用一些原型(prototype)以及大量的壓力測試來確保估計的準確。
從單體AdServer改為多產品競價器架構后,AdServer對直接下游服務的請求數量增加,進而增加所有下游服務的壓力和成本。考慮到這一點,我們謹慎地選擇了要分割的產品垂直領域,以使我們獲得最大的投資回報。
發布平臺改動的發布周期變長
把AdServer按產品切分還意味著每一個平臺層面的改動都要在所有產品上完成測試和發布。我們清楚認識到、并且愿意承擔這個成本。
哪怕有上述不足,在競價器架構正式上線后,我們還是看到了產品隔離的好處。一個具體的例子是,我們通過給Promoted Trend競價器中的選擇服務配置一個緩存,實現延遲的降低,而完全不影響其它產品的行為。我們還看到產品功能的迭代不再被平臺團隊所阻塞,解決了一個主要的痛點。
總結
所有定律都有局限性,康威定律也不例外。它適用于所有的組織,但我們也可以共同努力打破它,確保服務和組織都適合未來的需求,而不是受制于歷史。切分并不能解決所有問題,但對團隊以及服務確實有積極的影響,其結果是產品工程師在新架構中添加新功能的工作流程得到了簡化。當我們開始這個項目的時候,這似乎是一個幾乎不可能完成的任務,但回過頭來看,它不僅幫助我們搭建了更健康的系統,還加深了對系統工作方式的理解,為實現Twitter廣告部門的下一個宏偉目標奠定了基礎。
特別聲明:以上文章內容僅代表作者本人觀點,不代表ESG跨境電商觀點或立場。如有關于作品內容、版權或其它問題請于作品發表后的30日內與ESG跨境電商聯系。
二維碼加載中...
使用微信掃一掃登錄
使用賬號密碼登錄
平臺顧問
微信掃一掃
馬上聯系在線顧問
小程序
ESG跨境小程序
手機入駐更便捷
返回頂部