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