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