面試官:怎樣設計一個分布式任務調度平臺?
大家好,我是君哥。
在工作中,批量任務調度的需求經常會遇到,比如下面的幾個場景:
- 數據遷移:從數據庫 A 批量讀取數據,加工后把數據寫入數據庫 B;
- 消息通知:運營商批量給客戶發送短信;
- 批量扣款:在還款日,銀行批量扣除貸款客戶的當期還款金額;
- 賬務加工:系統通過日終跑批的方式加工當天的賬務數據。
從開源框架來看,優秀的分布式任務調度框架并不少,比如 Quartz、Spring Batch、xxl-job、PowerJob 等。如果公司不使用開源框架,要自研一套,該如何設計呢?
今天就來聊一聊怎樣設計一套分布式任務調度平臺。
1.觸發器
既然是任務調度,那觸發器肯定是必不可少的。觸發器就是控制任務什么時間開始執行,使用者可以定義好 Cron 表達式,到時間保證任務被觸發。
除了定時觸發外,也要設計通用的觸發接口,方便地給外部系統提供觸發入口。
在一些對賬類的場景,可能多個系統聯合對賬,上游系統加工好后把賬務文件送過來,觸發本系統的批量任務進行對賬。本系統對賬完成后,要把對賬結果異步通知給調用方。
2.調度器
調度器的主要作用是給待執行任務找到一臺合適的機器,然后把它調度到這臺集群上的待執行隊列。
(1)調度策略
調度器的調度策略可以有幾種:
- 調度到固定一臺機器;
- 以輪詢方式調度到下一臺機器;
- 根據集群中各機器的資源狀況調度到一臺空閑的機器,這個比較難一些;
- 隨機選擇一臺機器;
- 所有機器都執行。
在集群環境下,調度器對定時任務的作用是非常重要的,調度不好,很容易導致任務在不同機器上重復執行。
同時,調度器可以根據機器的資源情況進行任務調度,提高任務執行效率。
當然,也可能會有廣播的場景,這時調度器需要把任務調度到所有的機器上執行。
還需要考慮的一個點就是任務優先級,優先級高的任務需要優先調度。
3.執行器
調度器把任務調度到某一個機器上后,就把任務交給了執行器。執行器可以定義一個線程池,接到任務后把任務丟到線程池中,等待被線程池調度。
執行器可以提供一個基類,任務類通過繼承這個基類被調度平臺識別。
4.任務鏈
任務鏈也是非常重要的概念,在任務調度平臺上要支持任務鏈的定義,比如 task1->task2->task3 這樣一條任務鏈,task1 執行完成后觸發 task2,task2 執行完成后觸發 task3。
任務鏈使用的業務場景很多。比如一個復雜度高、耗時很長的任務,可以拆分成多個子任務,這樣如果有一個任務失敗了,把異常問題解決后,從失敗任務節點重新調起就可以。
實現任務鏈的方法有多種,這里提供兩個思路供參考,一個是不定義任務鏈,給每個任務定義一個子任務,觸發時只觸發第一個任務,任務執行完成后執行子任務;第二個方法是定義一個任務鏈,任務鏈明確任務依賴關系。
5.熔斷
批量任務一般用于處理數據量大的任務,比如給 10 萬個客戶發送短信通知。這會對本系統資源消耗較大,也可能會對下游系統造成壓力。
如果沒有任何防控手段,很可能會因為下游系統接口響應慢造成系統連鎖反應。有了熔斷能力,系統就可以及時發現問題并做出反應,對本系統和下游系統進行保護。
6.異常處理
異常處理的手段也是必要的。異常處理可以包含下面功能:
- 用戶可以方便地查看異常;
- 解決異常后,可以方便地重新發起任務;
- 遇到一些任務因為異常原因耗時太長,可以中斷任務;
- 遇到任務執行時間長,長時間占用系統資源,可以把任務掛起,給其他任務執行時間,其他任務執行完后可以再恢復這個任務。
7.阻塞控制
對于單機執行的任務,遇到任務排隊的情況很正常。可以設置阻塞策略,比如按照 FIFO 方式進行排隊執行,或者不做排隊,有正在執行的任務時直接丟棄。
8.服務注冊/發現
前面說到調度器會把任務調度到其中一臺機器執行,那為了方便地管理集群中的機器,服務注冊和發現功能也是很必要的。
9.任務監控
好多跑批任務是在日終執行,比如凌晨。把任務加入公司的監控體系,如果任務失敗,觸發監控告警,可以讓運維人員和研發人員第一時間感知到。
10.控制臺
有了上面的討論,控制臺的作用就很重要的。可以包括:
- 觸發器配置;
- 觸發類型配置;
- 調度器配置;
- 執行器配置;
- 任務和子任務配置;
- 異常處理;
- 阻塞控制策略配置;
- 任務執行狀態查詢;
- 集群管理。
11.總結
通過本文的討論,我們設計一個任務調度平臺,需要下面的功能,希望對你設計和理解任務調度平臺有所幫助。