作業幫基於 DolphinScheduler 的數據開發平臺實踐

作者 | 張迎

策劃 | Tina

摘 要

隨着任務數量、任務類型需求不斷增長,對我們的數據開發平臺提出了更高的要求。本文主要分享我們將調度引擎升級到 Apache DolphinScheduler 的實踐經驗,以及對數據開發平臺的一些思考。

1. 背景

首先介紹下我們的大數據平臺架構:

數據計算層承接了全公司的數據開發需求,負責運行各類指標計算任務。

其中批計算任務運行在 UDA 數據開發平臺,支持任務全鏈路的開發場景:開發、調試、環境隔離、運維、監控。這些功能的支持、任務的穩定運行,強依賴底層的調度系統。

原有調度系統是 2015 年 (抑或更早) 自研的,隨着任務類型新增、任務數量增多,暴露出諸多問題:

1. 穩定性:頻繁出現 mysql 連接不釋放、鎖超時等問題;數據庫壓力進一步導致調度性能瓶頸,任務無法及時調度。

2. 可維護性:核心調度器通過 php 開發,代碼古老又經歷多次交接,外圍模塊實現時採用了 go java python 多種語言;再加上功能上也存在單點,維護成本很高。

3. 擴展性:業務高速發展,不同任務類型需求越來越多,但是調度作爲底層服務在支撐上一直力不從心。

4. 可觀測性:由於是定時 nohup 啓動任務進程的方式,經常出現任務跑飛了的情況,系統暴露出來的可觀測指標幾乎爲 0。

對調度系統的核心訴求,我覺得分爲功能和系統兩部分:

功能上,調度系統的核心能力是解決數倉構建的依賴調度問題,因此需要支持多種依賴形式;支持豐富的任務類型,同時可擴展自定義新的任務類型。以及上線管控、歷史版本回滾、任務血緣等提高易用性的能力。

系統上,穩定性是第一位的,因此需要具備高可用的能力。同時支持租戶隔離、線性擴展、可觀測,以方便的對系統進行開發、維護和預警。

歷史上我們調研過 Airflow、DolphinScheduler 等多種選型,在過去大概一年的時間裡,我們將大部分任務從自研調度系統遷移到了 DolphinScheduler 上。

當前調度系統概況如下:

1. 任務類型上:HiveSQL、SparkSQL、DorisSQL、PrestoSQL、部分 shell 任務,均通過 DolphinScheduler 調度;遺留部分 shell 任務在原調度系統。

2. 任務數量上:DolphinScheduler 天級別調度數萬工作流實例,數十萬任務實例,高峰時期同時運行 4K+ 工作流實例。遷移完成後,預計工作流實例實例數翻倍。

2. 數據開發平臺實踐

2.1. 基於 DolphinScheduler 的改造

對 DolphinScheduler 的改造圍繞穩定性和易用性展開,對於原有調度系統設計良好的功能,需要兼容以降低任務遷移成本。

我們基於 DolphinScheduler 做了如下升級:

由於 DolphinScheduler 的架構設計比較好,優化基本上可以圍繞單點或者複用現有能力展開,而無需對架構進行大刀闊斧的改造。

我們的 SQL 任務都是多個 SQL 組成,但是原生的 SQL 任務只能提交單個。爲了確保系統簡潔,我沒有引入各類 client(hive-client、spark-client 等),而是通過 SQL 解析、連接池管理方式重構等方式,通過 JDBC 協議支持了單任務多 SQL 的提交。

同時充分複用了 DolphinScheduler 對於數據源的設計,賦予數據源更多的屬性,比如連接不同的 HiveServer2、Kyubbi、Presto Coordinator 等,對於計算運行在 Yarn 上的任務,單個數據源也只允許使用單個隊列。對數據源增加權限控制,這樣不同任務就只能使用有權限的集羣資源。

我們將資源文件、DQL 運行的結果數據,都統一上傳到了騰訊雲的 COS 對象存儲,以確保做到 Worker 真正的無狀態。(注:日誌上傳進行中)

此外包括對負載均衡進行優化、多業務線的租戶調度隔離、數據庫使用優化等。

2.2. 平滑的大規模遷移

儘管兩個調度系統,在功能以及架構上存在巨大差異,但是需要做到平滑的遷移,主要三個原因:

1. 原有調度系統服務多年,用戶對於功能設計、系統專有字段名詞等都已經養成習慣

2. 2W+ 工作流的遷移預計耗時較久,涵蓋公司衆多重要數據流,問題影響程度高

3. 用戶覆蓋了公司衆多業務線 (平臺、直播課、硬件、圖書),問題影響面廣

如此大規模的遷移我們做到了對用戶幾乎無感知,主要依賴新舊調度系統的打通和 DIFF。

接下來介紹下具體是怎麼做的。

2.2.1. 新舊調度系統打通

任務遷移階段,一部分任務運行在新的調度系統上,一部分運行在原有調度系統上,就需要解決兩個問題:

1. 用戶能夠查看所有任務實例的運行情況,包括一些內部已經習慣的調度名詞 (run_index、result_ftp、log_ftp、csv_result_path 等),這部分信息在 DolphinScheduler 調度裡顯然沒有

2. 任務和任務之間有依賴關係,兩個系統間調度任務時,也需要查詢對方系統調度的任務實例狀態,用於判斷當前任務依賴是否就緒。

因此,我們在遷移階段,架構是這樣:

核心設計有兩處。

首先任務實例狀態統一到原調度系統數據庫,對平臺而言:

1. 查詢方式、字段、API 跟之前一致

2. 任務更新時,如果該任務已經遷移到了新調度系統,則同時更新 DolphinScheduler 裡的工作流定義

因此平臺在使用上,對用戶沒有感知。

其次我們修改了 DolphinScheduler DependentTaskProcessor 的代碼,支持查詢 DolphinScheduler 及原有調度系統的任務實例狀態。這樣 DolphinScheduler 調度的任務,就可以自由依賴兩個調度系統的任務實例了。

因此在調度能力上,也做到了對用戶沒有感知。

上述架構,未來在遷移完成後,就可以僅通過 UDA-API + DolphinScheduler 提供完整的調度能力了。

同時,我們在配置依賴的易用性上也做了優化,歷史上支持了多種依賴方式:文件依賴、任務依賴、hql 依賴、prestosql 依賴等。後兩者都需要用戶手動配置查詢對應表,我們都優化爲了表依賴。平臺解析用戶的 sql,針對讀取的表,自動添加對應的依賴。既提高了易用性,也對用戶屏蔽了底層具體表存儲類型 (Hive/Presto/Iceberg/...) 的細節:

對任務依賴,也支持了全局搜索、偏移量、偏移單位以進一步提高易用性。

2.2.2. 新舊調度系統 DIFF

其次是新舊調度系統的 DIFF.

作爲基礎平臺,服務的業務線衆多,再加上 YARN 資源極其緊張,因此我們對調度系統的穩定性要求很高。爲了確保遷移順利,專門基於 DolphinScheduler DryRun 的能力做了一版定製:

所謂鏡像任務,是指我們在遷移新調度之前,會先在 DolphinScheduler 鏡像一份完全相同的任務,任務同樣經過變量替換等操作,只是該任務標記了不真正執行。

這樣我們就可以比較兩個系統間的 DIFF,主要包括:

調度時間是否基本一致:用於驗證依賴配置、定時設置等的兼容性

SQL 是否完全一致:驗證變量替換、SQL 屏蔽、隊列配置後,真正提交的 SQL 是否完全相同

經過上述空跑觀察一段時間,確保無 diff 後,線上任務就真正遷移到新的調度引擎上了。

2.2.3. 系統的可觀測性

在有限的時間裡,我們做了上述準備,但是仍然不夠充分。

系統需要具備良好的可觀測性,DolphinScheduler 對外提供了 Prometheus 格式的基礎指標。我們增加了一些高優指標,同時轉化爲 Falcon 格式對接到公司內部的監控系統。

通過監控大盤來查看調度系統的健康狀況,並針對不同級別的指標和閾值,配置電話 / 釘釘報警:

可觀測性提高後,分析問題的人力成本也得到控制,例如對於這種曲線:

容易觀察到在非工作時間曲線值基本爲 0,因此就能判斷指標異常 (=1) 很可能是用戶修改後觸發的,相比之前出現問題只能靠猜和逐臺機器登錄分析日誌的方式,通過 metrics 分析能夠更早發現和預警問題。

在遷移啓動後,對於 misfire、worker 線程池飽和度、連接池飽和度、io-util、overload 等指標,都重點關注和評估,以確保遷移順利。

2.3. 遷移收益

目前遷移已經進行了一大半,我們針對新舊調度系統的數據庫以及調度機資源使用做了對比:

數據庫:

QPS: 10000+ -> 500

負載:4.0 -> 1.0

資源使用降低 65%

我們在遷移過程中,通過 DolphinScheduler 以極低的開發成本支持了 SparkSQL、DorisSQL,以及高版本 PrestoSQL 這類業務新的調度需求。

功能上的其他對比:

3. 未來規劃

1. 例行任務、調試能力全部遷移 DolphinScheduler,沉澱線上操作 SOP

2. 結合社區的容器化進度,實現模塊 K8S 部署。當前 API 模塊已經在生產環境使用,Worker、Master 進行中

3. 全鏈路的一鍵數據回溯能力

4. 離線、實時平臺打通