網易嚴選實時計算平臺建設實踐

分享嘉賓:王傑瑞 (前) 網易 資深服務端研發

編輯整理:宋靈城

出品平臺:DataFunTalk

導讀: 本次主要分享網易嚴選在實時平臺建設方面的一些經驗,從如下幾個方面展開:

背景介紹

1. 發展歷程

網易嚴選是一家電商平臺,我們的業務鏈路主要涉及商品採購,銷售,物流以及售後等一系列服務,擁有非常豐富的數據業務使用場景,在很多業務決策上都需要用到實時的數據來進行分析,因此,平臺本身對數據的時效性和準確性有很高的要求。

從 2017 年開始,我們進行平臺化的建設,在整個過程中,我們的發展歷程如上圖所示:

2. 平臺現狀

目前,整個平臺大概運行了 5000 多個任務,每天峯值流量可以達到每秒 2000 萬左右,平臺從數據採集到對外提供服務,整體延時在秒級別。在網易嚴選,實時計算覆蓋的場景非常豐富,比如:實時大屏,實時風控算法,日誌業務監控以及 APM 預警等基礎服務方面的應用。

3. 平臺架構

上圖是我們實時計算平臺的整體架構圖,最底層是數據的基建層,主要提供了 kafka、pulsar 等消息隊列,Yarn、K8s 等計算資源以及其他存儲組件。

在數據基礎架構層之上,我們做了一個服務化的抽象,主要是爲了屏蔽 Flink 任務和底層基礎設施的交互過程,以服務的形式開放給上層平臺或第三方系統。

再往上是平臺層,是應用開發的主要入口,我們向用戶提供了開發運維等使用功能,以及監控報警等基礎功能,同時我們也提供了元數據管理,血緣分析等任務治理方面的工具。

在平臺層的基礎上,我們基於實時計算構建了豐富的應用,比如 ETL,數倉,風控等一系列數據方面的應用。

實時任務 SQL 化

在大數據領域,無論是實時計算還是離線計算,整體的發展趨勢都是朝着 SQL 化的方向在演進。我們平臺建設之初,用戶需要使用 java 或者 scala 自行編寫 Flink 任務 jar 包,託管到平臺上運行。這種方式存在兩個問題:一個是開發門檻相對較高,另一個問題是在任務調試和線上調優時非常困難。所以我們希望提供一個能開箱即用的開發環境,來降低用戶使用實時計算的門檻。

上圖是 Atom 開發平臺,是我們提供的 FlinkSQL 開發 IDE,用戶可以在這裏完成整個任務的開發,調試以及上線等過程,並且 Atom 集成了統一元數據,UDF 倉庫以及版本控制等基礎功能,能進一步提升用戶開發 SQL 任務的效率。

SQL 平臺的設計思路主要圍繞如下四個方面展開:

1. 統一元數據管理

在元數據管理方面,初期我們通過 DDL 語句將外部存儲以表的形式映射到 FlinkSQL 中,這樣做存在明顯的缺點,一個是使用起來非常繁瑣,另一個是應用之間服務無法複用。因此爲了避免開發前的繁瑣工作,我們對主流的存儲(比如:kafka,Hbase 等)做了全方位的打通,用戶開發過程中不需要關心具體的消息格式問題,IDE 會提供統一的格式解析插件來處理。

2. UDF 管理

在 UDF 方面,首先我們對 FlinkSQL 本身所欠缺但是很常用服務做了擴展,比如說 Json 解析,時間處理以及近似去重等。另外,我們提供了 UDF 倉庫,類似於 maven 倉庫,用戶可以自由的去上傳自定義的 UDF,倉庫會對這些 UDF 做統一的管理和複用,等它發佈後,這些 UDF 就可以在不同開發人員之間共享。當一個任務需要引用某一個 UDF 後,平臺會自動去完成資源的加載和 UDF 的註冊。

3. 功能擴展

4. 任務提交與調試

在任務提交和調試方面,目前我們採用將用戶提交的 SQL 編譯成 JobGraph,然後提交到集羣去運行,在這個過程中也會去加載任務所依賴的各種 connector 和 UDF 等一系列的資源。

另外,平臺提供了調試模式來支持在線調試 FlinkSQL 任務,在調試模式下,平臺會對 SQL 進行改寫,然後實時攔截調試的輸出結果,來讓用戶及時觀察任務的運行結果,同時調試的過程中可以自定義的制定線上數據採樣的時間段,使調試更加靈活與準確。

Flink 服務化

服務化是爲了簡化我們對任務管理的複雜度,對於上層的應用或者整個平臺來說,可以屏蔽掉 Flink 與底層資源的交互細節,上層的平臺可直接通過 rest 或者 RPC 與服務層進行交互來操作任務,比如控制任務的起停,狀態監聽或者觀察 checkpoint 和 savepoint 等,同時還提供了任務失敗自動恢復等機制。

我們通過插件的方式來支持多版本的 Flink 任務,不同的版本可以共存;平臺也可以支持底層的計算資源的多樣性,可以通過插拔的方式切換多個 yarn 或者 K8s 集羣。

通過服務化的方式,我們就可以將整個實時計算的生產能力開放出去,不僅僅是供我們的平臺使用,而是可以提供給其他服務使用,比如日誌平臺或者監控平臺等,這些平臺的實時計算需求,就可以直接通過服務化的接口統一處理。

1. 資源優化

隨着任務數越來越多,作爲平臺方就需要進一步考慮資源優化問題。在講具體優化之前我們先對比下 Flink 常用的兩種部署模式:

綜合分析上面兩種部署模式的優缺點後,我們做了一些改進措施。採用了基於 session 的一種新部署模式。通過提供任務資源策略和資源池的方式來提高 session 模式下的資源方式。我們抽象出一個資源策略的概念,即根據作業的類型,以及它的對資源申請的需求做的一個抽象,通過這個資源策略來劃分不同的資源池。當提交一個任務時,平臺會根據它所聲明的資源策略來選擇性的決定該任務應該分配到哪一個資源池的哪一個 session 中,這樣分配一方面可以複用 jobManager 和 taskManager 的計算資源,另一方面可以保證在同一個 session 中,所運行的任務的資源申請粒度是一致的。所以在這種模式下,可以實現平臺在任務的隔離性和資源利用率之間的相對平衡。

2. 雲原生部署

在服務化的過程中,我們還完成了任務雲原生的部署方式。在早期平臺任務都部署在 Yarn 集羣上,因爲一些歷史原因,Yarn 集羣沒有使用 cgroup 等方式做 CPU 的資源隔離,這常常出現同一機器上的不同任務 CPU 資源佔用的情況。而且整個 Yarn 集羣是基於物理機來部署的,當需要對集羣資源做臨時的擴容時就顯得非常不方便,且週期很長。另外,整體的運維人力成本也比較高。所以我們考慮使用 K8s 來代替 Yarn 集羣,K8s 的主要優點是資源隔離相對徹底,而且支持快速的彈性擴縮容,這樣就可以滿足我們多類型任務的混合部署,從而提升計算資源的整體利用率。

在網易嚴選,我們在 2019 年底,基於 Flink1.6 版本完成了 Flink on k8s 的落地。並且在 2020 年,完成 Flink1.10 版本的整合,目前平臺任務的容器化部署覆蓋率超過 80%。同時根據業務需要,我們還做了一些自適應的擴展。具體擴展如下所示:

數據治理

如上圖是網易嚴選在數據處理中的整體鏈路,通過分層的結構來支持數倉的需求。從圖中可以看到整體鏈路比較長,且任務之間的依賴關係複雜,所以我們需要對整個數據體系進行全鏈路的治理。數據治理的目的就是爲了保障數據能夠高效穩定的產出,同時推進全鏈路的資源優化。

1. 任務監控

在數據治理過程中,我們需要完善對任務處理情況的監控,比如像風控等業務,對任務的穩定性和時效性比較敏感,無法容忍任務長時間故障或者異常延遲等。Flink 本身提供了豐富的 metrics 指標用來監控任務全生命週期的健康情況,但是當任務數量越來越多時,Flink metrics 的體量也會非常大,我們經過調研和對比常用的時序數據庫後,選擇使用 OpenTSDB 來作爲 metrics 的存儲,同時通過加鹽哈希的方式來分散存儲和查詢熱點。另外,我們統一爲各種連接器提供訪問延遲、緩存命中等多項指標,同時將指標的粒度細化到算子級別,方便我們定位和排查問題。

2. 數據血緣追蹤

在數據治理中另一個重要的基礎服務是對數據血緣的管理,Flink 任務中 SQL 任務,我們通過對 SQL 做語法樹的遍歷來拿到它血緣情況,而針對用戶自定義的 jar 任務,需要在生成 JobGraph 時獲取它的 DAG 結構,然後通過反射機制來獲取血緣的元數據。統一的血緣管理,可以清晰的獲取到任務的上下游關係,方便問題的快速定位和排查。

3. 全鏈路數據治理

依託我們提供的統一元數據、任務監控以及統一血緣管理這三個基礎服務,我們就可以對數據做全鏈路治理。在數據治理中,我們主要從兩個維度來考慮。

首先是表的維度,所謂表,在實時中大部分指 kafka,而在離線中指 hive 等各種存儲。依賴於全鏈路的數據,我們可以建立數據的訪問模型,通過模型可以很好的識別表的冷熱情況,然後針對不同的情況做一些分級的治理。比如在 kafka 這一塊,我們會對一些熱點表做資源分區的調整及擴容,而對一些無效的表,我們會自動的清除。

其次是任務的維度,依託對任務的全生命週期管理以及監控指標的聚合分析,通過智能診斷框架去自動識別任務的問題所在,比如任務延遲,數據傾斜、反壓以及資源不足等,然後通過進一步的分析,對任務做資源的優化及調整。

通過全鏈路的數據治理,我們把任務的延遲控制在秒以內,提升了平臺的整體穩定性。

後續規劃

1. 流批一體探索

在流批一體的探索過程中,目前我們初步完成了 Iceberg 數據湖的集成,接下來會進一步探索計算及存儲層面的批流一體架構。

2. 作業智能診斷優化

進一步強化作業智能診斷能力,引入作業管控服務,當診斷框架給出調優方案之後,通過作業管控服務自適應的對任務做具體的調優,從而減少人工的介入,提升作業整體的可用性。

06

精彩問答

Q:存在 update 情況下,Flinksink 到下游輸出時,如何實現冪等性?比如 Flink 寫到 Hbase 如何實現冪等性?

A:FlinkSQL 本身在 retract 模式或者 upsert 模式下,若下游存儲存在主鍵,比如 Hbase 的 rowKey,更新或者刪除操作都是根據主鍵來實現,所以結果是具有冪等性的。若下游存儲沒有主鍵,比如 kafka,就需要下游存儲自身做冪等的操作,這種情況會更復雜。

Q:用戶對調試功能需求高嗎? 其主要的實現思路是什麼?

A:實際業務開發過程中,FlinkSQL 通常會比較複雜,代碼量比較大,所以很難一次性完整的寫出來,所以調試功能的使用是非常高頻的。無論是構造的數據還是採樣線上的數據,我們在調試模式下需要及時的展現這段 SQL 的結果,方便用戶來判斷其 SQL 的邏輯是否達到自己想要的效果,實現思路大概是:對 SQL 任務 source 和 sink 做替換,對 source,我們會實現 Kafka 採樣的功能或使用用戶上傳的樣例數據,對 sink,我們會替換成 webSocket 輸出或者文件輸出,方便用戶的查看。

今天的分享就到這裏,謝謝大家。

分享嘉賓:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/i5kGaRvVlYx0gtA2wrRfvA