作者 | 弘遠君
導讀
本文以百度垂類離線計算系統的演進方向為主線,詳細描述搜索垂類離線計算系統發展過程中遇到的問題,以及對應的解決方案。架構演進過程中一直奉行“沒有最好的架構,只有最合適的架構”的宗旨,面對不同階段遇到的問題,給出了適合的解決方案。尤其是近10年來的超大規模系統架構的升級, 一方面需要考慮系統本身的通用性和適配性,以滿足多個業務方的需求;另一方面需要結合系統當前運行的特點,在易用性、穩定性、智能化等不同方面進行提升。希望讀者能在了解系統演進的過程中獲得一些啟發。
01相關背景介紹
在過去,用戶通過“百度一下”得到的搜索結果是從互聯網上抓取來的結果,也被稱為“自然結果”。隨著網絡信息日益豐富,自然結果不能有效滿足用戶需求。為了解決自然結果無法滿足搜索需求的問題,提出了針對各個垂類深耕的搜索結果的解決方案,一方面為用戶帶來的更優質的內容,讓用戶體驗即搜即得的便捷,另一方面也可以幫助優質內容生產者提升訪問量。
隨著業務發展,除了標準通用的業務處理需求變更之外,越來越多的業務有自定義代碼的更新需求。通過自定義數據處理,一方面,產品負責同學可以將原始傳入的數據按照業務需求進行定制化處理,將原始數據轉化為最終搜索的結果數據。 另一方面,通用默認的一些功能機制限制了少量垂類的發展,業務希望引入更多的策略 模型邏輯 信號等處理以及打分機制,提升排序召回的效果。
在這樣的背景下,業務對于數據加工計算的框架引擎的需求越來越強烈,并且功能也逐漸成為整個垂搜離線處理過程中不可或缺的一部分。
02計算系統演進過程
百度搜索系統離線數據處理從時間線的發展階段來說一共經歷如下幾個階段:
a.原始離線處理系統: 本階段主要是實現業務加工入口從0到1的構建。整體上還沒有形成完備的框架體系并且開發成本較高,并且所有業務邏輯混在一個公共服務中,不同數據通過不同配置調用不同的策略邏輯。
b.業務離線處理架構: 本階段初步形成一整套的業務服務處理框架,有統一的服務框架和開發階段,實現了云原生和服務隔離的模式。
c.Serverless架構: 本階段業務的接入效率上進一步提高,業務從管理服務面向轉向管理業務加工函數,業務只需注冊函數就可以快速測試上線,同時支持容器實例的自動伸縮,使得在業務的使用效率得到的極大提升的同時相應資源成本急劇壓縮。
d.數據智能架構: 在原有服務部署的基礎上同時實現了數據的管理,從函數管理進一步升級成為需求管理,實現多語言服務框架支持的基礎上,成本進一步壓縮&效率提升。
03計算系統核心設計核心思路
&核心實現
下面詳細闡述各個階段的詳細特點以及核心實現。
3.1 原始離線處理系統
這套架構應用于2018以前,當時垂類的發展整體屬于起步階段。該階段業務主要的需求就是可以將原始的業務數據直接上線。架構的主要精力聚焦于通用業務能力的建設。隨著業務的逐步深耕,發現有少量的業務慢慢演化出來自定義加工的需求。
根據當時的業務需求,最終從原有的數據加工模塊中衍生出業務數據加工系統。當前階段的數據加工處理方式是使用統一Handler處理方式,當然這個處理并非是必選項,多數業務仍然不需要自定義加工處理。各業務之間也完全沒有數據隔離,這種架構最核心的意義就是從無到有提供業務的自定義加工能力。如下圖所示,此時計算系統只包含計算引擎部分,其他系統完全沒有建設。下面會對該系統的部分細節進行詳細說明。
3.1.1 業務特點
這個時期的業務特點主要有兩個:
多數業務,核心訴求最主要的是通用能力的建設。
個別業務,有少量簡單的自定義加工處理的需求。
所以這個時間點的核心主要是為了解決業務加工入口的問題。
3.1.2 核心設計
初版本的離線架構模塊非常簡單,如下圖所示藍色部分。隨著業務發展,為了滿足業務自定義加工的需求,引入紅色數據通路,其中統一數據加工模塊就是主要處理業務自定義加工邏輯。
如上圖所示,灰色部分是業務外層接入的數據系統,最開始的時候只有XML、POST 和 數據隊列的這種模式。藍色部分就是業務沒有自定義時候原始的數據框架代碼。紅色部分就是為了針對業務自定義需求引入的框架模塊:
用戶數據代理:主要是為了適配業務數據接入方式,數據的協議打平,主要是不同用戶協議的RPC做建庫層的數據轉化。
用戶通用需求:主要是為用戶共性需求做統一處理,會根據不同業務的不同配置做功能處理:比如業務圖片視頻的轉化處理,業務用戶版本管理處理以及用戶的核心機制等。
統一數據加工模塊:主要是為了統一用戶數據的加工處理,主要是給所有接入的業務的數據提供了一個可以數據加工的入口。
3.2 業務處理架構
如上文所述3.1架構核心價值是自定義加工能力的從0到1的建設,然而隨著業務的快速發展,越來越多的業務需要自定義加工能力。業務自定義加工的需求從原來個位數迅速膨脹了10倍。因此,為了滿足業務在自定義開發上易用性和穩定性的訴求,將原來3.1的中心化的處理模式升級成為服務框架的模式。總體上來說,當前階段的計算系統建設已經基本具備了服務層和業務層兩層:
業務層:業務通過平臺已經基本上可以實現,基礎的服務管理。
服務層:對計算引擎進行重構,讓新的服務框架支持業務的高效開發。
下面會對該系統的部分細節進行詳細說明。
3.2.1 業務特點
由于3.1中上一代系統數十個業務自定義需求統一在同一個模塊里面開發&統一線上運行,遇到了主要如下幾方面問題:
效率:業務在相同的模塊里面開發,導致業務開發上線的過程中經常遇到沖突,以及上線排隊的問題,導致整體生效周期比較長。
穩定性:由于這種業務流量混合的模式隔離性比較差,導致單個業務出問題,經常會影響所有的業務。
因此,架構構建出完善的服務框架,業務可以基于服務框架構建自己的業務代碼,從效率和穩定性兩個方面解決上述問題:
效率:服務開發上線的過程是完全隔離的,業務在開發上線的過程中完全沒有業務阻塞,整體服務上線周期從天級縮短到小時級別。
穩定性:由于每個業務服務執行邏輯都有完全獨立的app,導致業務的穩定性大大提升,不會存在業務之間的互相影響。
3.2.3 核心設計
業務處理框架:建設一個數據處理框架,業務可以基于這個框架來實現自己的業務處理功能。
任務平臺:每個任務注冊、升級、管理都可以通過任務平臺來進行管理。
統一網關:所有數據的統一入口,統一接收上游數據,并且做數據的轉發和分發。
業務APP:每個業務都有自己獨立服務的app,每個業務開發是基于框架的獨立分支開發,上線是每個業務單獨上線,業務處理的服務流量也都是完全隔離的。
3.3 Serverless架構
如上文中3.2表述已經解決系統隔離性的問題,業務快速發展從最開始的幾十個,發展到上百個業務應用。當業務發展到井噴狀態后,服務框架的形式已經完全不能滿足業務的開發需求。
Serverless架構如下圖所示,此時計算系統整體版圖已經相對完善,相比上一代計算架構,不僅僅業務層包含的全流程的優化,提供了完整的工具功能;服務層充分考慮的架構的設計和復用,同時增加控制層增加智能調度的功能針對系統流量進行資源的動態調度。
下面會對該系統的部分細節進行詳細說明。
3.3.1 業務特點&解決問題
業務學習成本:大量的新業務接入需要進行開發,導致框架本身學習成本需要幾天的時間,新業務的接入和開發的時間基本上都在周級別。
資源如何節省:大量的業務也帶來app的高速膨脹,原來接入的數百臺機器已經用滿,到了資源瓶頸,當前的資源量無法支持業務的快速膨脹。
3.3.3 核心設計
應用層:針對于基礎服務架構,上面給業務開放的各種云服務,從業務的 接入、開發到后面的調試、測試,到服務上線后的監控。
服務層:這部分是整體架構的基礎,應用層都是基于這里進行開發的,這部分是整個系統的基石,屬于整體系統的核心框架。
調度層:通過根據流量形式的擴縮容,保證后續服務可以自動化的進行服務操作。
下面重點介紹一下 服務層的主要內容,對業務來說主要包含兩部分:
極致抽象的業務框架:是核心框架基礎中的基礎,提供新的開發范式同時,為后續智能調度奠定良好基礎。
高度復用的基礎服務:強大豐富的后端服務能力封裝,支持業務低成本復用,降低開發成本同時提升穩定性。同時系統還提供強大的編排能力,低成本支持業務從簡單到復雜的發展。
極致抽象的業務框架
業務框架作為FaaS層和業務代碼的載體,是整個業務邏輯的代碼框架。框架本身維護數據流語義,面向有向無環圖(DAG)的數據流,調用業務函數代碼。業務框架是面向有向無環圖的數據流實時計算,基于公司基礎的數據流框架支持完備的流式計算語義,結合業務場景需要功能構建出業務框架:
如上圖左邊就是用戶實際的執行代碼,對于函數的接口定義:入參和返回值都是Dict類型。業務的代碼邏輯直接在函數中實現,需要變更的數據,如上圖所示業務在根目錄下增加了一個時間戳字段,然后把更新后的結果傳遞給下游。
業務端使用開發成本低的腳本語言進行開發(例如Python),基礎服務框架使用C++實現,結合數據壓縮、批處理、數據預分發等機制,使得業務可以在簡化服務框架開發同時優化服務運行性能。通過架構層面的優化策略來達到服務性能和開發成本的平衡。
高度復用的基礎服務
業務依賴的后端服務,包括多媒體長留服務,數據存儲服務,策略計算等十項服務能力,所有的服務架構的支持目標都是通過簡單配置、少量代碼的方式進行服務接入。
架構通用能力:包括索引處理(倒排、正排、向量索引),數據審核(政治敏感數據/色情數據識別&過濾),多路分發、數據建庫等能力。
與業務聯合研發的能力:數據的低質過濾能力(實現數據清洗/歸一化/數據去重/類目拼接),數據多元融合,數據質量打分計算(質量打分/作弊識別/物料打分)。
基于公司強大基礎能力: 多媒體處理服務(外鏈轉內鏈/OCR/水印計算/重復圖計算/主體識別/視頻轉儲等),自然語言處理服務,數據沉淀服務。
支持的基礎服務(BaaS服務)主要是兩個特點:簡單穩定 & 充分集成公司內其他優質能力。用戶通過SDK調用、算子復用和數據流復用等方式直接進行能力復用,完全不需要進行服務的部署和管理,服務易用性、穩定性由搜索中臺來處理。使用任何服務后端都可以收口在一個地方,避免業務頻繁跟多個服務團隊進行交流處理,極大降低業務使用成本。業務最開始接入通常只需要簡單的少數功能(例如,修改部分字段的信息),多數業務直接用我們提供的平臺化的開發模板即可完成開發。但是隨著業務的逐步深耕,業務逐步使用,業務會向復雜逐步過渡,例如搜索中臺某業務通過復用數十種能力的組合使用,建設出具有深度定制的數據系統。
3.4 數據智能架構
如上文中3.3 表述已經很大程度上解決業務接入效率的問題并且在資源的使用效率上實現根據流量的擴縮容實現的資源極大程度的節省,業務的app的數量已經發展到上千個,業務對于效率、成本、服務質量提出來更高的要求。至此已經構建出,從業務層、邏輯層、服務層、控制層的四層架構,實現離線計算系統從指令式計算系統到聲明式計算系統的徹底轉變。
3.4.1 業務特點
效率業務的迭代開發很多都是針對少數幾個字段,但是當前業務同學仍然需要了解服務全拓撲才能開發。
隨著業務復雜深耕業務的開發迭代業務開發者出現多語言開發情況來提高服務的開發和執行效率。
業務如何實現新類目的快速接入、在不了解全面的情況下快速迭代。
計算引擎執行效率更高,用更少的資源計算跑更多的服務資源。
業務問題能不能快速定位&發現以及問題的自動處理。
3.4.2 核心思路
從設計思路來看當前系統架構是上一代架構的拓展:
數據管理:出了原始服務管理外,引入數據全面管理,為列計算奠定基礎。
編排能力:將原來業務手動編排的函數能力擴展成為需求聲明式自動編排的能力。
服務處理:極致高效的服務處理能力,支持多種不同業務開發者的高效開發效率,將整體的計算從行計算轉向列計算,提高整體的計算復用。
控制能力:將原來自動伸縮的能力擴展成為智能控制能力,做到問題的自動識別、自動分發、自動分析 和 自動處理。
整體架構的設計核心理念大致是多層抽象、分層復用。
3.4.3 核心設計
當前階段的核心設計已經呈現出完整的四層架構的抽象能力:
應用層:業務直接可見的相關服務,包括業務從開始數據接入到服務運行的全周期各階段各種應用。
邏輯層:也可以稱之為編排層,負責將原始的業務需求表達轉化成為線上真實運行的服務, 業務通過Codeless 平臺化選擇勾選自己的功能集合,以及對應數據映射關系進行提交,將用戶提供的功能 & 數據的綁定關系轉化為業務的自定義的功能 以及映射關系。
服務層:計算系統的核心,業務實際計算運行在這層,主要包含計算引擎 和服務架構兩部分。向上承接邏輯層的編排結果運行服務,向下提供基礎信號作為控制層的輸入。
控制層:包含智能調度和智能控制兩部分:智能控制主要是通過自動接受業務指標數據進行智能控制保證服務穩定,而智能調度是除了根據數據流量進行進行自動伸縮以外還可以根據業務服務關系進行流量復用,減少業務的重復計算。
下面我們針對部分核心系統(如上圖藍色部分)的設計作展開說明。
需求表達邏輯
需求邏輯的表達的核心就是如何把用戶原始的功能需求轉化成真是線上服務的算子、配置、關系的表達。用戶最原始的輸入包含兩部分:
業務數據:業務數據需要功能的最小單位進行切割,后續算子進行配置轉化以及服務綁定的列式計算。這里說的有點繞口,其實本質上就是把業務數據的原始Proto或者數據Schema注冊一下就可以。
功能集合:功能集合既可以用戶直接使用的系統提供的默認模版的功能集合 也可以是用戶通過平臺自定義的集合,值的注意的是每個功能都都有其指定的傳入參數,比如圖片計算,需要傳入圖片URL,向量計算需要傳入原始數據 & 向量參數等等。功能完成后也會有對應的輸出結果業務可以指定。
獲取完成用戶的原始輸入后,架構通過兩層邏輯映射的方式,將原始用戶需求轉化成為線上服務部署信息:
需求表達服務:用戶的原始需求轉化為功能模版的組合。這個階段會根據用戶配置,將原始算子和數據進行綁定,原始用戶抽象的需求實例化成帶數據的算子集合。
需求編排服務:通過業務算子的本身的依賴關系和數據依賴的血緣關系進行表達組合,將帶數據的算子構建出N個有向無環圖。
整體需求表達都可以通過Codeless方式表達,通過描述功能集合數據集合描述方式,加之兩層邏輯映射的轉化,這樣就可以將原始用戶聲明式需求直接轉化線上服務關系和系統配置,并且服務的算子的拓撲關系完全可以通過業務的數據關系表達自動化推導出來, 實現了95%以上的功能可以完全自動化配置實現,當然有個別服務無法低成本轉化表達的,也提供了人工接口。
計算引擎實現
計算引擎層的核心組件大致分成兩部分,圖計算引擎 & 多語言算子的執行引擎 。
圖計算引擎:主要控制的業務拓撲的表達關系,通過有向無環圖來表達。
算子執行引擎:主要控制業務真實業務函數的執行,不同語言有不同的函數實現,例如Python、GoLang、C/C++都有自己的執行引擎。
下面針對兩部分進行仔細說明
線程管理:每個業務算子默認都是多線程的分發模式(如果業務算子只支持單線程,可以把線程數設置成1)。
分發模式:數據消費分發模式默認是輪詢分發,固定KEY分發(實現保序)以及按消費能力分發。
數據壓縮:這個默認支持常見數據壓縮方法,是可選的吞吐優化手段,支持LZ4、Gzip、Snappy等常見壓縮算法。
圖計算引擎實現:實現的核心功能就是實現支持表達有向無環圖的框架,使用C++實現的,圖下圖部分中,藍色部分就是有向無環圖的框架實現,當然我們這個框架的底層實現支持了多種數據的表達:
本地隊列表達:如圖左下角部分表達的就是一個簡單的拓撲表達,拓撲關系是通過本地的無鎖隊列進行串聯的,每個隊列下面掛載一個業務算子,業務算子處理完成數據后,算子拓撲配置管理分發到下游的本地隊列中,如果是最后一個算子,數據結果全部處理完成后輸出到遠程隊列Producer中。左側這邊是框架內部的通用功能:
遠程隊列表達:每個藍色大框表示一個具體實例,實例之間使用遠程隊列交互,如果每個實例里面只有一個業務算子,這種的交互方式類似于遠程隊列的表達方式。
混合方式表達:更多使用方式是混合使用,一個巨型拓撲會拆分成多個子拓撲,每個子拓撲使用本地隊列的方式進行表達,而子拓撲之間使用遠程隊列的方式進行表達。
多語言引擎執行層:語言執行層整體框架整體根據不同的語言有不同實現模式,大體上分成三部分:編譯型、解釋型、原生C++。
解釋型:最典型的就是Python實現方式,這種方式也是過去同學最喜歡用的開發語言之一。圖上圖最上面,左邊灰色部分是C++開發的部分,最右邊黃色部分是業務代碼,中間這部分就是C++轉Python的交互引擎調用。這種方式的本質就C++的開發引擎使用PyBind實現指定接口服務解釋器,根據指定的數據序列化和反序列化方式進行操作,在函數調用時再實時轉化為python的Dict。
編譯型:典型是Golang的使用方式。與Python的實現類似,左邊灰色部分是C++開發的部分,最右邊黃色部分是Golang業務代碼,中間是C++轉Golang的交互引擎。Golang的實現相比Python的方式有點復雜,本質是通過原生CGO作為用戶接口,為了統一用戶接口層,其實分成兩部分:左半部分是直接跟C++交互,直接用C++實現負責把原生C++轉化為基礎的C類型的函數指針進行調用。右半部分使用Golang實現負責把原生序列化好的函數反序列化成業務結構體,然后再進行真正調用。
原生C++:這里很多人可能覺得奇怪,C++不是也是編譯型的么,已經有編譯型的實現模式何必畫蛇添足,增加這么一種實現模式,其實本質不然,golang雖然是編譯型語言,底層框架的實現由于盡量考慮通用性,數據傳遞的過程中勢必需要進行序列化和反序列操作,而在原生的C++的實現過程中我們在實現的過程完全摒棄所有的序列化和反序列操作,數據在本地隊列中的傳遞完全是業務的數據指針(而非序列化數據),而每個業務算子在處理數據過程中,直接根據原始的數據指針通過反射機制(實現方式有很多最簡單的 map)可以直接獲取對應列的數據項,整個過程無鎖的超高效率。這里的核心優化思路數據鏈式處理過程。拉鏈上的每個算子,都共享同一個輸入和輸出。每個算子,其實就是一個接口相同的函數,這樣就可以隨意地調整函數指針的組合,形成不同的處理鏈。比如:一個請求走 A 模型排序,一個請求要走 B 模型排序,他們可以共享前序的算子,只在最后一個算子有所不同。在鏈式處理基礎上,算子也可以是繼承同一基類接口的派生類,或者 lambda 表達式。結合工廠模式等一些編程技巧,處理鏈的調整可以配置化、動態化、腳本化。實測執行業務單算子普通的純數據項帶分支的多節點的拓撲計算單機(單線程/算子)可以達到數十萬的處理能力。
通過新計算引擎的實現從使用上完全兼容上一代計算系統的使用方式,將不常使用的功能做精簡,同時優化復雜拓撲執行方式,通過架構層也業務層解耦,支持多語言高效執行方式,對于老業務平遷的數據框架平均計算效率提高5~10倍,同時業務由于針對性建設業務框架業務開發效率進一步提升。
智能控制實現
自動化問題分析引擎是整個智能控制系統的大腦。它上游接收觀測提供的原始數據,進行自動的分析決策后,通過系統提供的自愈能力處理。自動化問題分析引擎的核心思路: 只要歷史上出現過的問題,RD同學能找到問題和解決方案,就可以轉化為系統規則和后置函數梳理。那當下一次遇到問題則無需人工干預。規則引擎的核心分析過程是2段式的:
階段1: 傳統配置化的規則引擎的配置(上圖中右上角黃色部分),配置多個采集指標項的邏輯關系(與或交非), 這里主要是針對問題的基礎分析功能,判定規則是否觸發。
階段2: 基于這個基礎分析的結果,進行后置Function的執行分析,這個主要是針對復雜問題的分析補充, 最終執行引擎根據這個返回結果進行函數執行。
下面針對問題分析引擎的執行結果如下:
前提: 開發者需要配置好處理邏輯規則(以及規則依賴的數據項,必填) & 回調函數(選填)。
數據解析器: 數據解析器主要承擔的數據的原始抽取的工作,一共分成如下3步:
a.配置解析: 邏輯執行根據開發者配置的數據信息解析;
b.數據抽取: 根據解析出來的配置通過數據接口進行獲取,可以從統一接口根據配置的信息從不同的介質充抽取所需求的信息;
c.數據歸一化: 將不同介質的原始數據歸一化成為統一的數據格式供規則管理器使用。
規則管理器: 規則管理器主要承擔核心的邏輯分析工作,一共分成如下幾步:
a.規則解析: 根據開發者配置的規則邏輯,將原始配置信息,解釋成原始的規則樹。
b.執行計算: 根據數據解析器提供的數據結果和配置的函數規則分別執行計算。執行計算過程中最重要的就是基礎分析器,整體提供了5大基礎能力,數十種常見的邏輯計算來輔助規則配置。
c.規則邏輯運算: 根據上層解析出來的規則樹 和 每個數據項執行完成的計算結果進行邏輯運算,并根據執行的結果確定是否進行高級數據分析器,如果判斷結果為真則根據所配置的后置函數進行處理。
高級數據分析器: 如圖所示有兩種模式,對于簡單基礎分析可以判斷結果的,直接給默認的處理函數進行數據拓傳;對于簡單邏輯規則無法準確表達的,開發者可以自定義后置分析函數, 函數會將原始數據和基礎計算的計算結果作為參數傳出來,開發者只需要通過處理后的數據描述清楚分析邏輯即可。
動作執行器: 就是這個分析器的真正的執行引擎,根據規則運算的結果中包含的參數進行動態調整。
通過智能控制系統的建設,月級別分析處理上萬的異常問題,自動恢復的比例占總數的95%以上,絕大多數的問題幾分鐘內完成自動恢復, 核心故障同比減少60% (由于預處理防止普通問題惡化成嚴重問題)。
04結論以及展望
本文全篇以離線計算系統的發展為主線,貫穿全文講解遇到的問題以及解決方案。尤其是當前新一代架構核心就是以數據+功能為核心的聲明式的設計,配合高效計算引擎、配合智能化的設計,把整體的離線計算系統的高度做了進一步提升。設計中其實還是雖然解決了過去的很多問題,但是仍然有不完善的地方,當然當前的效果還遠沒有達到最終的理想狀態,部分系統功能有待持續性的打磨升級。
審核編輯:湯梓紅
-
模塊
+關注
關注
7文章
2695瀏覽量
47431 -
百度
+關注
關注
9文章
2268瀏覽量
90361 -
C++
+關注
關注
22文章
2108瀏覽量
73618 -
計算系統
+關注
關注
0文章
42瀏覽量
10287
原文標題:百度垂類離線計算系統發展歷程
文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論