1. 程式人生 > >EasyScheduler大資料排程系統架構分享

EasyScheduler大資料排程系統架構分享

EasyScheduler大資料排程系統架構分享

導語

EasyScheduler是易觀平臺自主研發的大資料分散式排程系統。主要解決資料研發ETL 錯綜複雜的依賴關係,而不能直觀監控任務健康狀態等問題。EasyScheduler以DAG流式的方式將Task組裝起來,可實時監控任務的執行狀態,同時支援重試、從指定節點恢復失敗、暫停及Kill任務等操作。

背景

任務排程系統在大資料平臺當中是一個核心的基礎設施,由於資料處理流程常常具有很長的依賴鏈條,因此依賴單機的crontab等單純依賴時間排程的方式,往往存在很大的弊端,如依賴不清晰,出錯難以查詢等問題,因此,我們調研了市面上流行的排程系統:

在這裡插入圖片描述

鑑於易觀日處理資料30多TB,複雜的 ETL依賴關係、易用性、可維護性及方便二次開發等綜合原因,我們開發了自己的大資料分散式排程系統EasyScheduler。

總架構設計

EasyScheduler設計圍繞四個服務展開,UI、Web、Server和Alert。

UI : 使用易觀封裝的Vue及jsplumb元件開發

Web:使用SpringBoot提供Rest Api和UI分離互動

Server : Scheduler排程及分散式任務執行引擎

Alert:告警微服務

以下將詳細分享Server端的設計思想和遇到的問題

去中心化vs 中心化

中心化思想

中心化的設計理念比較簡單,分散式叢集中的節點按照角色分工,大體上分為兩種角色:

Master的角色主要負責任務分發並監督Slave的健康狀態,可以動態的將任務均衡到Slave上,以致Slave節點不至於“忙死”或”閒死”的狀態。

Worker的角色主要負責任務的執行工作並維護和Master的心跳,以便Master可以分配任務給Slave。

中心化思想設計存在的問題:

一旦Master出現了問題,則群龍無首,整個叢集就崩潰。為了解決這個問題,大多數Master/Slave架構模式都採用了主備Master的設計方案,可以是熱備或者冷備,也可以是自動切換或手動切換,而且越來越多的新系統都開始具備自動選舉切換Master的能力,以提升系統的可用性。

另外一個問題是如果Scheduler在Master上,雖然可以支援一個DAG中不同的任務執行在不同的機器上,但是會產生Master的過負載。如果Scheduler在Slave上,則一個DAG中所有的任務都只能在某一臺機器上進行作業提交,則並行任務比較多的時候,Slave的壓力可能會比較大。

去中心化


去中心化設計裡,通常沒有Master/Slave的概念,所有的角色都是一樣的,地位是平等的,全球網際網路就是一個典型的去中心化的分散式系統,聯網的任意節點裝置down機,都只會影響很小範圍的功能。

去中心化設計的核心設計在於整個分散式系統中不存在一個區別於其他節點的”管理者”,因此不存在單點故障問題。但由於不存在” 管理者”節點所以每個節點都需要跟其他節點通訊才得到必須要的機器資訊,而分散式系統通訊的不可靠行,則大大增加了上述功能的實現難度。

實際上,真正去中心化的分散式系統並不多見。反而動態中心化分散式系統正在不斷湧出。在這種架構下,叢集中的管理者是被動態選擇出來的,而不是預置的,並且叢集在發生故障的時候,叢集的節點會自發的舉行"會議"選舉新的"管理者"主持工作。最典型的案例就是ZooKeeper及Go語言實現的Etcd。

EasyScheduler的去中心化是Master/Worker註冊到Zookeeper中,實現Master叢集和Worker叢集無中心,並使用Zookeeper分散式鎖來選舉其中的一臺Master或Worker為“管理者”來執行任務。

分散式鎖實踐

EasyScheduler使用Zookeeper分散式鎖來實現同一時刻只有一臺Master執行Scheduler,或者只有一臺Worker執行任務的提交。

獲取分散式鎖的核心流程演算法如下:
在這裡插入圖片描述

EasyScheduler中Scheduler執行緒分散式鎖實現流程圖:
在這裡插入圖片描述

執行緒不足,迴圈等待問題

如果一個DAG中沒有子流程,則如果Command中的資料條數大於執行緒池設定的閾值,則直接流程等待或失敗。

如果一個大的DAG中嵌套了很多子流程,如下圖:

則會產生“死等”狀態。MainFlowThread等待SubFlowThread1結束,

SubFlowThread1等待SubFlowThread2結束,SubFlowThread2等待SubFlowThread3結束,而SubFlowThread3等待執行緒池有新執行緒,則整個DAG流程不能結束,從而其中的執行緒也不能釋放。這樣就形成的子父流程迴圈等待的狀態。此時除非啟動新的Master來增加執行緒來打破這樣的”僵局”,否則排程叢集將不能再使用。

對於啟動新Master來打破僵局,似乎有點差強人意,於是我們提出了以下三種方案來降低這種風險:

1. 計算所有Master的執行緒總和,然後對每一個DAG需要計算其需要的執行緒數,也就是在DAG流程執行之前做預計算。因為是多Master執行緒池,所以匯流排程數不太可能實時獲取。

2. 對單Master執行緒池進行判斷,如果執行緒池已經滿了,則讓執行緒直接失敗。

3. 增加一種資源不足的Command型別,如果執行緒池不足,則將主流程掛起。這樣執行緒池就有了新的執行緒,可以讓資源不足掛起的流程重新喚醒執行。

注意:Master Scheduler執行緒在獲取Command的時候是FIFO的方式執行的。

於是我們選擇了第三種方式來解決執行緒不足的問題。

容錯設計

EasyScheduler容錯設計依賴於Zookeeper的Watcher機制,實現原理如圖:

Master監控其他Master和Worker的目錄,如果監聽到remove事件,則會根據具體的業務邏輯進行流程例項容錯或者任務例項容錯。

Master容錯流程圖:

在這裡插入圖片描述

ZooKeeper Master容錯完成之後則重新由EasyScheduler中Scheduler執行緒排程,遍歷 DAG 找到”正在執行”和“提交成功”的任務,對”正在執行”的任務監控其任務例項的狀態,對”提交成功”的任務需要判斷Task Queue中是否已經存在,如果存在則同樣監控任務例項的狀態,如果不存在則重新提交任務例項。

Worker容錯流程圖:

Master Scheduler執行緒一旦發現任務例項為” 需要容錯”狀態,則接管任務並進行重新提交。

注意:由於” 網路抖動”可能會使得節點短時間內失去和zk的心跳,從而發生節點的remove事件。對於這種情況,我們使用最簡單的方式,那就是節點一旦和zk發生超時連線,則直接將Master或Worker服務停掉。

Logback和gRPC實現日誌訪問

由於Web和Worker不一定在同一臺機器上,所以檢視日誌不能像查詢本地檔案那樣。有兩種方案:

將日誌放到ES搜尋引擎上

通過gRPC通訊獲取遠端日誌資訊

介於考慮到儘可能的EasyScheduler的輕量級性,所以選擇了gRPC實現遠端訪問日誌資訊。

我們使用自定義Logback的FileAppender和Filter功能,實現每個任務例項生成一個日誌檔案。

FileAppender實現如下:

以…/流程定義id/流程例項id/任務例項id.log的形式生成日誌。

過濾匹配以TaskLogInfo開始的執行緒名稱:

總結

本章從排程出發,介紹了易觀自主研發的大資料分散式排程系統,著重介紹了EasyScheduler的架構原理及實現思路。

EasyScheduler由在工作流排程方面工作多年的幾位小夥伴研發而成,致力於成為大資料平臺的中流砥柱,使排程變得更加容易,更可以從其中文名“易排程”看出我們的初衷,如果你對目前市面上的排程不夠滿意,非常歡迎試用易排程,歡迎大家加入進來,提出需求,也歡迎貢獻程式碼, 易排程即將開源, 如果想在開源前使用,請聯絡我們!

http://geek.analysys.cn/topic/24