摘要:本文整理自螞蟻集團高級技術(shù)專家纺讲、螞蟻集團流計算平臺負責(zé)人李志剛,在 Flink Forward Asia 2022 平臺建設(shè)專場的分享囤屹。本篇內(nèi)容主要分為四個部分:
主要挑戰(zhàn)
架構(gòu)方案
核心技術(shù)介紹
未來規(guī)劃
一熬甚、主要挑戰(zhàn)
1.1 金融場景業(yè)務(wù)特點介紹
第一部分是時效性。金融場景追求時效性肋坚,特別是一些風(fēng)控類的業(yè)務(wù)乡括。首先,無論是宕機還是其他風(fēng)險情況冲簿,對業(yè)務(wù)的影響需要在秒級以內(nèi)粟判。其次,業(yè)務(wù)邏輯經(jīng)常變更峦剔,不能影響時效性。最后吝沫,金融業(yè)務(wù)上下游依賴特別復(fù)雜呻澜,需要保證時效性不受到影響。
第二部分是正確性惨险。金融數(shù)據(jù)在任何情況下羹幸,計算出來數(shù)據(jù)必須保證 100%正確。不能因為出現(xiàn)任何故障或者其他問題導(dǎo)致數(shù)據(jù)出錯辫愉,一旦數(shù)據(jù)出錯業(yè)務(wù)是不可接受的栅受。當(dāng)前很多業(yè)務(wù)都是先開發(fā)一套離線的數(shù)據(jù)模型,然后再開發(fā)實時的數(shù)據(jù)模型恭朗,這兩邊如果使用了不同的引擎屏镊,就這會導(dǎo)致數(shù)據(jù)核對相當(dāng)困難。如果數(shù)據(jù)出現(xiàn)問題痰腮,我們需要像寫 JAVA 代碼或者 C++代碼一樣而芥,有比較方便的調(diào)試技術(shù),發(fā)現(xiàn)問題所在膀值,并進行修正棍丐。
第三部分是穩(wěn)定性误辑。螞蟻業(yè)務(wù)混布在大的物理集群,有在線業(yè)務(wù)歌逢、離線業(yè)務(wù)巾钉、實時業(yè)務(wù)。在如此復(fù)雜趋翻、多變睛琳、混布的環(huán)境下,需要保證實時業(yè)務(wù)的穩(wěn)定性踏烙,不能因為在云化環(huán)境下的 K8s 組件或者其他組件影響實時業(yè)務(wù)师骗。在申請?zhí)貏e大的 Pod 資源時,時間會特別長讨惩,就滿足不了實時業(yè)務(wù)的秒級標(biāo)準(zhǔn)辟癌。由于金融場景這些特點,我們提出創(chuàng)新的解決方案荐捻。
1.2 螞蟻流計算業(yè)務(wù)的基本情況
流計算規(guī)模大概在 78w Core黍少,1.2w+個流作業(yè),所有的集群都運行在云原生的集群上处面。我們每年支撐的大促活動特別多厂置,支持 15 次以上的大促活動。由于大促業(yè)務(wù)會經(jīng)常變化魂角,需要動態(tài)的彈性計算能力昵济。
1.3 流計算業(yè)務(wù)的主要挑戰(zhàn)
近幾年,實時計算的技術(shù)處于穩(wěn)定期野揪,在彈性方面的挑戰(zhàn)有以下部分:
在大促常態(tài)化后访忿,集群可以隨時擴縮容。
在混布環(huán)境下斯稳,如何保證實時業(yè)務(wù)的穩(wěn)定性海铆。不能因為別的業(yè)務(wù)影響到實時計算穩(wěn)定性。
流計算最核心的技術(shù)是優(yōu)化狀態(tài)的性能挣惰。如何極致優(yōu)化狀態(tài)性能卧斟,保證在任何大數(shù)據(jù) Join 或者窗口的情況下沒有性能問題。
在易用性方面的挑戰(zhàn)有以下部分:
- 金融業(yè)務(wù)或者 BI 業(yè)務(wù)會隨時進行變更憎茂。如何在變更的情況下珍语,快速重啟作業(yè)。
- 如何解決 SQL 作業(yè)調(diào)試難問題唇辨。
- 如何做到流批統(tǒng)一。
1.4 應(yīng)對挑戰(zhàn)的方法
在易用性方面能耻,我們的解決方案是:
- 對實時計算平臺進行改造赏枚,提出熱啟動技術(shù)亡驰,解決在云化環(huán)境下啟動慢的問題。
- 調(diào)試 SQL 代碼像在 IDEA 調(diào)試 JAVA 代碼一樣饿幅,解決排查數(shù)據(jù)困難的難題凡辱。
- 提出了基于 Flink 的流批統(tǒng)一的開發(fā)平臺。
在彈性方面栗恩,因為大促活動非常多透乾,需要隨時擴縮容。所以我們的解決方案是:
- 基于 K8s 全面進行混布磕秤。
- 對 Flink 原生的 K8s 模式進行改造乳乌,提出云原生的 Flink 集群模式,避免由于 K8s 的問題導(dǎo)致影響實時業(yè)務(wù)穩(wěn)定性市咆。
二汉操、架構(gòu)方案
<p style="text-align:center">螞蟻實時計算平臺的架構(gòu)圖</p>
最底層是 K8s 平臺,上一層是 Flink runtime 流批一體蒙兰,螞蟻流計算的核心技術(shù)磷瘤。提出了 K8s 集群模式,采用開源社區(qū) DophinScheduler 來實現(xiàn)工作流的調(diào)度搜变。
核心技術(shù)包括內(nèi)存優(yōu)化采缚、窗口優(yōu)化、復(fù)雜多變的云化環(huán)境下的智能診斷(如何發(fā)現(xiàn)問題挠他,問題的定位等)扳抽;調(diào)節(jié)流計算作業(yè)的參數(shù)困難,因此提出基于 AI 學(xué)習(xí)算法自動化解決調(diào)參問題绩社;社區(qū)版本 RocksDB 狀態(tài)在某些情況下性能不好摔蓝,我們做了狀態(tài)存儲 AntKV,相比 RocksDB 性能有兩倍的提升愉耙。
提出了調(diào)試 SQL贮尉,像調(diào)試 JAVA 代碼一樣方便的功能;熱啟動解決作業(yè)啟動速度慢的問題朴沿;用戶只要寫一套 SQL 作業(yè)猜谚,指定跑流模式還是批模式,解決用戶不用寫兩套代碼和其他開發(fā)的問題赌渣。
三魏铅、核心技術(shù)介紹
3.1 熱啟動技術(shù)
第一部分,為什么需要熱啟動技術(shù)坚芜?
首先览芳,開發(fā)實時作業(yè)的人都知道,修改作業(yè)參數(shù)鸿竖,比如內(nèi)存沧竟、并發(fā)等铸敏,改完之后重啟整個作業(yè)的時間特別長。特別在云原生環(huán)境下悟泵,提交作業(yè)杈笔、申請 Pod、Pod 發(fā)下來糕非、拉起鏡像等一系列流程蒙具,要花費幾分鐘。對于金融的實時業(yè)務(wù)來說很難接受朽肥。
其次是流量突變禁筏,在大促活動時,流量經(jīng)常會發(fā)生變化鞠呈。面對這種變化融师,我們需要快速適應(yīng)它,改并發(fā)蚁吝、內(nèi)存旱爆、UDF 的情況經(jīng)常發(fā)生。如果使用原生版本的 Flink窘茁,流程會特別長怀伦。從改,到提交山林,再到資源真正下來房待、作業(yè)跑起來等流程平均下來可能要四分鐘。
我們要怎么解決呢驼抹?
我們提出了熱啟動技術(shù)桑孩,它的技術(shù)原理是用戶在前端界面,會請求一個 rest 服務(wù)框冀。然后我們把修改后的執(zhí)行計劃參數(shù)提供給 rest流椒,會做一些前置校驗。接著把前置校驗后的參數(shù)和執(zhí)行計劃明也,提到已經(jīng)在跑的那個作業(yè)上宣虾。當(dāng)它拿到新的執(zhí)行計劃后,會把舊的暫停温数,然后 cancel 掉绣硝,恢復(fù)之后再慢慢創(chuàng)建出來。
總的來說撑刺,把新的執(zhí)行計劃提上去鹉胖,把舊的暫停,然后根據(jù)新的執(zhí)行計劃生成新的部署模式。這么做的好處是甫菠,繞過了前面的 SQL 編譯階段败许,包括 SQL 下載 Jar 包等復(fù)雜的流程,節(jié)省了 Pod 申請的時間淑蔚,作業(yè)重啟操作在秒級完成。
<p style="text-align:center">熱啟動技術(shù)處理流程</p>
第一愕撰,將攜帶過來的新 JobGragh 和舊的 JobGragh 進行 merge刹衫,將舊的 JobGragh 中可以復(fù)用的數(shù)據(jù)進行回填到新的 JobGragh 中,包括 Jar 包搞挣、資源带迟、文件等。
第二囱桨,新的執(zhí)行計劃生成后仓犬,把舊的 Task、中間的 Checkpoint Coordinator 中間的協(xié)調(diào)節(jié)點暫停掉舍肠。
第三搀继,全部暫停后,把新的 JobGragh 調(diào)度起來翠语,加載新的狀態(tài)叽躯。如果新的執(zhí)行計劃調(diào)度失敗,需要有回滾技術(shù)肌括,回滾到上一個正常狀態(tài)点骑,保證用戶操作體驗的友好性。
<p style="text-align:center">熱啟動效果</p>
采用熱啟動技術(shù)谍夭,作業(yè)操作時間節(jié)省 90%以上黑滴。也就是說,原來大部分啟動作業(yè)需要 300 秒紧索,現(xiàn)在使用熱啟動技術(shù)只需要兩秒袁辈,甚至一秒。
3.2 K8S 集群模式
第二部分齐板,為什么需要 K8s 集群模式吵瞻?
- 上圖右側(cè)是開源社區(qū)版本提供的原生 K8s 提交 Flink 作業(yè)方式。首先 K8s Client 找 K8s 的 API Server 申請 K8s Service甘磨,K8s 啟動 K8s 的 deployment橡羞,然后拉起 Master 角色,再在 Master 里申請 Flink 需要的 Pod济舆,在 Pod 啟動 TaskManager 等流程卿泽。 這些復(fù)雜流程都依賴 K8s 組件,像 API Server、K8s Master签夭,這就會導(dǎo)致單點齐邦。一旦 API Server 出現(xiàn)升級或者故障,就會影響作業(yè)的提交第租、運維等措拇。在螞蟻實踐下來,歷史上出現(xiàn)過很多問題慎宾,碰到 K8s 集群升級會導(dǎo)致實時作業(yè)不能提交丐吓、運維。
- 申請大的資源 Pod 時趟据,時間就會特別漫長券犁,甚至是五分鐘級的,對用戶體驗特別糟糕汹碱。
- 申請大 Pod 32 核 64GB 的經(jīng)常失敗粘衬。
- 在實時業(yè)務(wù)大促活動時,不能動態(tài)的滿足業(yè)務(wù)新增資源需求咳促。
- K8s API Server 性能是有瓶頸的稚新。如果一次大批量創(chuàng)建幾百個 Pod,就會特別慢跪腹,容易超時枷莉。
為了解決以上問題,我們提出了 K8s 集群模式尺迂。
<p style="text-align:center">K8s 集群模式</p>
基本思路是先通過 Operator 向 K8s 申請大量資源笤妙,然后 ClusterManager 會把資源 hold 住。之后提交作業(yè)噪裕,就不用去找 K8s 的 API Server 或者 Master 申請 Service蹲盘、Deployment 等資源。
這樣有什么好處呢膳音?
首先召衔,可以減少或者不需要和 API Server、Master 打交道祭陷。其次苍凛,Pod 已經(jīng)申請在機器上,就不用每次提交作業(yè)的時候兵志,再申請新的 Pod醇蝴,可以節(jié)省大量時間。
從上圖可以看到:由于 K8s 組件導(dǎo)致的問題想罕,直接減少 95%悠栓。作業(yè)啟動的時間,從以前的 100 秒以上,減少到現(xiàn)在的 50 秒惭适,再加上熱啟動技術(shù)售淡,一兩秒就把作業(yè)啟動起來安拟。資源利用率提高了 5%扼劈。
3.3 流批一體技術(shù)
第三部分登舞,為什么需要流批一體技術(shù)?
假如要開發(fā) 800 個指標(biāo)的 BI 報表凄杯,后面發(fā)現(xiàn)了有 750 個要用離線開發(fā)师溅,有 650 個要用 Flink 實時開發(fā),中間還會有 500 個是重復(fù)的盾舌。重復(fù)的意思是離線也要做一套 SQL,實時也要做一套蘸鲸,但實際上它的業(yè)務(wù)邏輯是一模一樣的妖谴。這樣就會導(dǎo)致在數(shù)據(jù)開發(fā)的過程中,有很多重復(fù)工作酌摇。比如你用批引擎開發(fā)了一套膝舅,然后又用 Flink 實時引擎開發(fā)了一套,兩邊的 SQL 語法都不一樣窑多,核對起來就特別困難仍稀。為了解決當(dāng)前業(yè)務(wù)開發(fā)的痛點,就提出了螞蟻的流批一體技術(shù)埂息。
如上圖所示技潘,流批一體技術(shù)底層也在 K8s 上。再上一層我們用的是 Flink runtime千康。
在往上一層是插件化 shuffle service享幽、插件化調(diào)度、插件化狀態(tài)拾弃。
- 插件化 shuffle service值桩。shuffle service 在批計算非常重要,比如可以通過 shuffle service 解決在云化環(huán)境下本地盤很小的問題豪椿。
- 插件化調(diào)度奔坟。流和批的調(diào)度方式是不一樣的,調(diào)度也可以插件化搭盾。
- 插件化狀態(tài)咳秉。比如 RocksDB、內(nèi)存鸯隅、AntKV 型的狀態(tài)類型滴某。
最上面是平臺的統(tǒng)一入口。用戶在統(tǒng)一入口上可以選擇統(tǒng)一寫一套 SQL,然后指定跑流還是批霎奢,這樣就解決了寫兩套 SQL 的難題户誓。
<p style="text-align:center">Flink 調(diào)試技術(shù)</p>
開發(fā)的時候可能要寫一個批的 SQL 和流的 SQL。如果數(shù)據(jù)經(jīng)常有問題幕侠,寫 JAVA 代碼帝美、C++代碼都知道,使用 IDE 或者 GDB 等工具晤硕,進行單步調(diào)試悼潭。我們提出了對 SQL 代碼單步調(diào)試技術(shù)。方案有兩種:第一種方案舞箍,修改在 Flink 代碼里的所有算子舰褪,包括批的算子、流的算子疏橄。然后在入口處增加 trace 代碼占拍,即在入口處把輸入數(shù)據(jù)打出來,在輸出的地方把輸出數(shù)據(jù)打出來捎迫。但這個方案有一個問題晃酒,會侵入原生的 Flink 引擎代碼,導(dǎo)致代碼很不優(yōu)雅窄绒。第二種方案贝次,字節(jié)碼增強。
那么字節(jié)碼增強技術(shù)是怎么做的呢彰导?大家可能知道蛔翅,平時從 IDE 里調(diào)試 JAVA 代碼或別的代碼時,實際上底層是通過 JAVA agent 技術(shù)進行調(diào)試的位谋。JAVA agent 是一門技術(shù)搁宾,通過這個技術(shù)可以把類代理掉。也就是在執(zhí)行類之前 mock 掉新的類倔幼,然后自己控制這個新的類的行為盖腿。所以 JAVA agent 是通過把跑的類代理掉,然后通過代理跑真正要跑的類损同。從上圖右側(cè)可以看出翩腐,底層 Flink 引擎的代碼是不會改的。所以通過代理的方式膏燃,在類加載之前通過 JAVA agent 代理出改寫的新類茂卦。
新類主要分為兩部分,第一部分是 Stream Operator组哩。在執(zhí)行完 Stream Operator 后等龙,會插入輸入处渣、輸出的方法,這樣就可以把算子的輸入數(shù)據(jù)和輸出數(shù)據(jù)打印出來蛛砰,即通過 Byte Buddy 來實現(xiàn)類的改寫罐栈。
這里有一個問題,F(xiàn)link 代碼中有很多 codegen 代碼泥畅,運行的時候會自動生成一些動態(tài)代碼荠诬,就是把一些函數(shù)調(diào)用合成一個函數(shù)來執(zhí)行的。但通過 JAVA agent 的 Byte Buddy 改寫類的時候位仁,如果調(diào)用的是內(nèi)部方法就會有問題柑贞。
從上圖可以看出,通過 JAVA agent 技術(shù)對 codegen 進行類的重寫聂抢。先把 codegen 代碼下載一份到本地存儲起來钧嘶,再通過 Byte Buddy 把它改寫,之后再插入輸入輸出代碼琳疏,這樣就可以看到算子的輸入輸出有决。就像調(diào)試 JAVA 代碼一樣,輸入是什么轿亮、輸出是什么、下節(jié)點的輸入是什么胸墙、下節(jié)點的輸出是什么我注,都可以詳細的打印出來。
四迟隅、未來規(guī)劃
第一但骨,優(yōu)化 Flink 批性能、支持全向量化計算智袭。業(yè)界也有很多引擎在做全向量化計算奔缠,通過一些開源技術(shù),比如 Databricks 公司的全向量化計算引擎吼野,它的性能提升了兩倍以上校哎。
第二,基于機器學(xué)習(xí)的自動化調(diào)優(yōu)瞳步。由于流計算里的參數(shù)較多闷哆,用戶用起來有些門檻,我們將通過機器學(xué)習(xí)的方法來解決自動化調(diào)參數(shù)問題单起。
第三抱怔,發(fā)展基于 Flink 的湖倉技術(shù)。流批統(tǒng)一后嘀倒,存儲屈留、計算局冰、平臺都會統(tǒng)一,這樣一個入口就能解決用戶批灌危、流康二、AI、學(xué)習(xí)等所有計算需求乍狐。
第四赠摇,云化環(huán)境下智能化診斷。云化環(huán)境比較復(fù)雜浅蚪,出現(xiàn)問題很難排查到具體問題藕帜。我們提出了一個智能化診斷工具,它可以診斷到底層云化環(huán)境的情況惜傲,比如機器洽故、IP、機器負載等一系列情況盗誊,幫助用戶快速發(fā)現(xiàn)問題时甚。
第五,流批混合部署下分時調(diào)度哈踱,提升利用率荒适。流批不僅是引擎的統(tǒng)一,統(tǒng)一之后還要進一步提升資源的利用率开镣,我們將在提升利用率的方向上繼續(xù)努力刀诬。