大家好我是張金明,在蔚來汽車擔(dān)任大數(shù)據(jù)平臺(tái)研發(fā)工程師。這次和大家分享的是 Apache DolphinScheduler 在蔚來汽車一站式數(shù)據(jù)治理開發(fā)平臺(tái)的應(yīng)用和改造,接下來我將從背景、應(yīng)用現(xiàn)狀和技術(shù)改造三個(gè)方面去分享一下。
背景
業(yè)務(wù)痛點(diǎn)
在蔚來汽車構(gòu)建一個(gè)統(tǒng)一的數(shù)據(jù)中臺(tái)之前,我們面臨這樣一些業(yè)務(wù)痛點(diǎn)和困境:
-
數(shù)據(jù)缺乏治理,數(shù)倉不規(guī)范、不完整
- 沒有統(tǒng)一的數(shù)據(jù)倉庫,無全域的數(shù)據(jù)資產(chǎn)視圖
- 存在數(shù)據(jù)孤島;
-
工具散亂,用戶權(quán)限不統(tǒng)一、學(xué)習(xí)成本高
- 用戶需要在多個(gè)工具之間切換,導(dǎo)致開發(fā)效率降低
- 底層運(yùn)維成本高;
-
數(shù)據(jù)需求響應(yīng)周期長(zhǎng),找數(shù)難、取數(shù)難
- 無沉淀的數(shù)據(jù)資產(chǎn)與中臺(tái)能力,重復(fù)處理原始數(shù)據(jù);
- 業(yè)務(wù)數(shù)據(jù)需求從提出到獲取結(jié)果的周期長(zhǎng)
基于這些痛點(diǎn)和問題,我們構(gòu)建了一個(gè)公司層面的業(yè)務(wù)中臺(tái),內(nèi)部叫做 DataSight。
我們可以看到,最底下是我們的一些基礎(chǔ)組件;往上一層,這些基礎(chǔ)組件主要是支撐了一些數(shù)據(jù)接入與開發(fā)的模塊;再向上是我們的數(shù)據(jù)治理,以及數(shù)據(jù)資產(chǎn)與應(yīng)用層。其中,Apache DolphinScheduler 這個(gè)調(diào)度器在公司主要應(yīng)用于交互的模塊,就是數(shù)據(jù)開發(fā)和數(shù)據(jù)運(yùn)維兩個(gè)模塊。
數(shù)據(jù)開發(fā)中,調(diào)度任務(wù)開發(fā)主要就是用到了 Apache DolphinScheduler,通過 API 和調(diào)度器進(jìn)行交互。
應(yīng)用現(xiàn)狀
作業(yè)現(xiàn)狀
目前,我們的機(jī)器共有 9 臺(tái),分別是兩臺(tái) Master機(jī)器,是8c 和 32G;六臺(tái) Worker 機(jī)器,16c 和 64G,以及一臺(tái) Alert 機(jī)器,8c 和 32G。
版本是更新到了 Apache DolphinScheduler 2.0.7,后續(xù)的目標(biāo)是升級(jí)到 2.0.8 版本,2.0 版本已經(jīng)能夠支撐我們的業(yè)務(wù)了,整體的穩(wěn)定性還是比較好的。
我們其實(shí)是從 2022 年 4 月份開始才真正地在線上運(yùn)行 Apache DolphinScheduler,直到今天大概運(yùn)行了一年一個(gè)月多的時(shí)間,日均的調(diào)度工作流實(shí)例大概在 4w+,日均調(diào)度任務(wù)實(shí)例大概在 10w+ 左右,主要節(jié)點(diǎn)是 Spark 節(jié)點(diǎn)、SparkSQL、prestoSQL、Python 和 Shell,其中 Spark 節(jié)點(diǎn)占比約 70%。
目前這些節(jié)點(diǎn)已經(jīng)能夠支撐我們的大部分業(yè)務(wù),后續(xù)我們可能會(huì)把 DolphinScheduler 自帶的一些節(jié)點(diǎn)加到我們的數(shù)據(jù)開發(fā)模塊里面來。
技術(shù)改造
為了適應(yīng)我們業(yè)務(wù)的需求,我們對(duì) Apache DolphinScheduler 進(jìn)行了一些技術(shù)改造。首先是穩(wěn)定性方面的工作。
穩(wěn)定性
- 滾動(dòng)重啟+黑名單機(jī)制+精準(zhǔn)路由
這個(gè)改造是因?yàn)槲覀冇龅降囊恍┩袋c(diǎn),首先,大家知道,DolphinScheduler 的 Worker 重啟機(jī)制在重啟時(shí)會(huì)把所有的任務(wù)給 kill 掉,然后去Restart 這個(gè)任務(wù),把這個(gè) kill 的任務(wù)分發(fā)到新的 Worker 機(jī)器上。這樣會(huì)導(dǎo)致任務(wù)執(zhí)行時(shí)間較長(zhǎng)。這不符合我們的預(yù)期。
同時(shí),我們也無法在特定的 Worker 上進(jìn)行驗(yàn)證任務(wù)。
對(duì)此,我們的解決方案就是滾動(dòng)重啟,在重啟某臺(tái)機(jī)器之前先下線這臺(tái)機(jī)器,也就是加上黑名單,這樣的話,Master 機(jī)器就不會(huì)給這臺(tái)下已經(jīng)下線的機(jī)器去分發(fā) worker 任務(wù)。這臺(tái)機(jī)器會(huì)在上面的任務(wù)全部處理完畢后自動(dòng)上線,也就是移出這個(gè)黑名單。接下來所有的 woker 節(jié)點(diǎn)都按照此種方式重啟,達(dá)到平滑重啟的目的。
這樣做的好處在于不會(huì)阻塞每個(gè)任務(wù)的執(zhí)行,集群在重啟的時(shí)候穩(wěn)定性能得到大幅提升。
另外,我們還做了精準(zhǔn)路由的工作。也就是在任務(wù)名后加特定后綴,實(shí)現(xiàn)精準(zhǔn)路由到某臺(tái)機(jī)器上。
如圖所示,我們?cè)谶@個(gè)任務(wù)后面加一個(gè) specific dispatch-worker02 的話,那這個(gè)任務(wù)一定會(huì)被分配到Worker02 這臺(tái)機(jī)器上去。這樣的好處在于,假設(shè)我們想要去某一個(gè)功能點(diǎn),我們只需要把某一臺(tái) Worker 機(jī)器下線重啟,需要測(cè)試的功能點(diǎn)按照這個(gè)方式就一定能夠打到這臺(tái)特定的機(jī)器上去,實(shí)現(xiàn)最小范圍的灰度,有助于提高穩(wěn)定性。
- 優(yōu)化存儲(chǔ)
在存儲(chǔ)方面,我們痛點(diǎn)也很明顯,就是 process instance和task instance 這兩張表數(shù)據(jù)量是比較大的,由于我們每天的數(shù)據(jù)量比較大,目前已經(jīng)達(dá)到了千萬級(jí)別,造成 MySQL 的存儲(chǔ)壓力比較大。另外,部分 SQL 執(zhí)行時(shí)間長(zhǎng),業(yè)務(wù)響應(yīng)變慢;而且 DDL 時(shí)會(huì)造成鎖表,導(dǎo)致業(yè)務(wù)不可用。
針對(duì)這些問題,我們的解決方案包括去梳理所有的慢 SQL,然后去添加合適的索引。與此同時(shí),還有降低查詢頻率,特別是針對(duì)依賴節(jié)點(diǎn)。因?yàn)槲覀冎酪蕾嚬?jié)點(diǎn)每 5 秒鐘查詢一次數(shù)據(jù)庫,所以我們根據(jù)依賴節(jié)點(diǎn)所在的 tasks instance ID 去做一個(gè)“打散”,偶數(shù)節(jié)點(diǎn)每 30 秒查詢一次,奇數(shù)節(jié)點(diǎn)每 30 秒查詢一次,把他們分開來降低對(duì)整個(gè)數(shù)據(jù)庫的查詢壓力。
另外,為了減輕表數(shù)據(jù)量大的問題,我們也做了一個(gè)定期刪除的策略,以及定時(shí)同步歷史數(shù)據(jù)的策略。
定時(shí)刪除就是我們利用 DolphinScheduler 自身的調(diào)度能力建立兩個(gè)工作流去刪除這兩張表,保證 process instance 這張表保留兩個(gè)月的數(shù)據(jù),task instance 這張表保留一個(gè)月的數(shù)據(jù)。同時(shí)在刪表的時(shí)候,我們要注意在非業(yè)務(wù)高峰期時(shí)去做這個(gè)動(dòng)作,每次刪表的時(shí)候,batch size 要控制好,盡量不要影響線上的任務(wù)。
定時(shí)同步歷史數(shù)據(jù),就是我們針對(duì) process instance 這個(gè)表,依據(jù) schedule time 按年去分表;針對(duì) task instance 這張表,按 first submit time 按月去分表。
- Spark 任務(wù)優(yōu)化
我們提交 Spark 任務(wù)的方式是通過 Sparks Submit 去提交的,它的缺點(diǎn)在于提交 Spark 任務(wù)后,常駐機(jī)器,導(dǎo)致機(jī)器內(nèi)存過大,會(huì)有機(jī)器宕機(jī)的風(fēng)險(xiǎn),worker 的運(yùn)行效率較低。
我們優(yōu)化了 Spark 任務(wù)提交和運(yùn)行的邏輯,就是通過 Spark Submit 提交的時(shí)候添加 spark.yarn.submit.waitAppCompletion=false
這個(gè)參數(shù),這樣任務(wù)提交完以后這個(gè)進(jìn)程就消失了??紤]到要保證 worker 機(jī)器任務(wù)的線程和 Spark 和 Yarn 上的狀態(tài)一致,我們間隔一定時(shí)間查詢 Spark 任務(wù)狀態(tài),如圖所示:
這里是一個(gè) while true 循環(huán),首先去判斷這個(gè)任務(wù)是否超時(shí)。如果任務(wù)已經(jīng)超時(shí)就會(huì)結(jié)束這個(gè) Spark 任務(wù),同時(shí)會(huì) kill 掉集群上那個(gè)真正在跑的任務(wù)。
如果任務(wù)沒有超時(shí),我們會(huì)去獲取任務(wù)的狀態(tài),如果任務(wù)狀態(tài)是終止?fàn)顟B(tài),就直接跳出這個(gè)循環(huán),否則會(huì)間隔一定的時(shí)間,比如 30 秒,再繼續(xù)這個(gè) while true 循環(huán)。這種方式讓整個(gè) worker 機(jī)器所能承載的 Spark 任務(wù)大大增加。
易用性
接下來再看一些我們?cè)谝子眯苑矫娴母脑旃ぷ靼桑?/p>
- 依賴節(jié)點(diǎn)優(yōu)化
我們的依賴節(jié)點(diǎn)之前的痛點(diǎn)在于,它的使用規(guī)則不太符合用戶的需求,比如之前是單次查詢不到上游即失?。蝗罩緝?nèi)容顯示信息不全,對(duì)用戶不友好;用戶無法自定義依賴范圍。
針對(duì)這些問題,我們做的工作包括修改了查詢邏輯為繼續(xù)等待,就是說當(dāng)這個(gè)任務(wù)查詢不到上游的時(shí)候,我們會(huì)繼續(xù)等待,而不是直接失敗。同時(shí)我們會(huì)也有個(gè)極端的保證,就是這個(gè)依賴節(jié)點(diǎn)超過 24 小時(shí)以后就讓它自動(dòng)失敗,然后給用戶發(fā)一個(gè)報(bào)警。
針對(duì)依賴節(jié)點(diǎn),我們也做了強(qiáng)制成功這樣一個(gè)小trick,并支持用戶自定義依賴范圍。
另外,我們還優(yōu)化了依賴節(jié)點(diǎn)的日志輸出,當(dāng)用戶點(diǎn)擊依賴節(jié)點(diǎn)的日志的時(shí)候,可以比較清楚地看到依賴的上游所在的空間,這個(gè)空間內(nèi)任務(wù)所對(duì)應(yīng)的維護(hù)人是什么,以及工作流節(jié)點(diǎn)是什么和完成狀態(tài),讓用戶可以點(diǎn)對(duì)點(diǎn)地找到上游的同學(xué),快速解決這個(gè)依賴節(jié)點(diǎn)卡住的問題。
- 補(bǔ)數(shù)任務(wù)優(yōu)化
針對(duì)補(bǔ)數(shù)之前的痛點(diǎn),比如補(bǔ)數(shù)任務(wù)沒有進(jìn)度提示,
并行補(bǔ)數(shù)流程實(shí)例不嚴(yán)格按照時(shí)間順序,停止并行補(bǔ)數(shù)任務(wù)邏輯比較麻煩等問題,我們的解決方案包括并行任務(wù)引入線程池,也就是把任務(wù)按照時(shí)間順序一個(gè)一個(gè)拋到新建的線程池里,執(zhí)行完畢以后退出這個(gè)線程池,然后再放一個(gè)新的進(jìn)來,達(dá)到并行補(bǔ)數(shù)的狀態(tài)。同時(shí),執(zhí)行時(shí)間按遞增的順序。
當(dāng)我們想停止這個(gè)補(bǔ)數(shù)任務(wù)的時(shí)候也比較簡(jiǎn)單,直接把這個(gè)線程池 shutdown 就行。
- 多 SQL 執(zhí)行
最后是關(guān)于多 SQL 執(zhí)行方面的優(yōu)化。我們之前面臨的痛點(diǎn)包括:
- 多 SQL 需要多節(jié)點(diǎn)執(zhí)行浪費(fèi)集群資源;
- 自定義環(huán)境變量無法實(shí)現(xiàn);
- 無法跟蹤 SparkSQL 的運(yùn)行日志。
我們的解決方案包括拆分這條 SQL,支持多條 SQL 同時(shí)執(zhí)行。
與此同時(shí),我們可以在 SparkSQL 任務(wù)執(zhí)行之前攔截執(zhí)行select engine_id() as engine_id
語句。
如上圖所示,對(duì)于 SQL 1 和 SQL 2,之前我們會(huì)在兩個(gè)任務(wù)里面去放著,但是現(xiàn)在可以在一個(gè)任務(wù)節(jié)點(diǎn)里面放下來,它會(huì)執(zhí)行兩次。同時(shí)我們可以清晰地看到這個(gè) SparkSQL 所在的 application ID 是什么,用戶能夠清晰地根據(jù)這個(gè) application ID 找這個(gè)業(yè)務(wù)所在的地址,了解這個(gè)作業(yè)的進(jìn)度。文章來源:http://www.zghlxwxcb.cn/news/detail-501069.html
本文由 白鯨開源 提供發(fā)布支持!文章來源地址http://www.zghlxwxcb.cn/news/detail-501069.html
到了這里,關(guān)于日均調(diào)度 10W+ 任務(wù)實(shí)例,DolphinScheduler 在蔚來汽車一站式數(shù)據(jù)治理開發(fā)平臺(tái)的應(yīng)用改造的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!