0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

任務(wù)調(diào)度系統(tǒng)設(shè)計(jì)的核心邏輯

jf_ro2CN3Fa ? 來(lái)源:勇哥java實(shí)戰(zhàn)分享 ? 2024-01-02 15:09 ? 次閱讀

閱讀一篇「定時(shí)任務(wù)框架選型」的文章時(shí),一位網(wǎng)友的留言到了我:

我看過(guò)那么多所謂的教程,大部分都是教“如何使用工具”的,沒(méi)有多少是教“如何制作工具”的,能教“如何仿制工具”的都已經(jīng)是鳳毛麟角,中國(guó) 軟件行業(yè),缺的是真正可以“制作工具”的程序員,而絕對(duì)不缺那些“使用工具”的程序員!...... ”這個(gè)業(yè)界最不需要的就是“會(huì)使用XX工具的工程師”,而是“有創(chuàng)造力的軟件工程師”!業(yè)界所有的飯碗,本質(zhì)就是“有創(chuàng)造力的軟件工程師”提供出來(lái)的??!

寫(xiě)這篇文章,想和大家從頭到腳說(shuō)說(shuō)任務(wù)調(diào)度,希望大家讀完之后,能夠理解實(shí)現(xiàn)一個(gè)任務(wù)調(diào)度系統(tǒng)的核心邏輯。

25b753ac-a880-11ee-8b88-92fbcf53809c.png

1 Quartz

Quartz是一款Java開(kāi)源任務(wù)調(diào)度框架,也是很多Java工程師接觸任務(wù)調(diào)度的起點(diǎn)。

下圖顯示了任務(wù)調(diào)度的整體流程:

25c65730-a880-11ee-8b88-92fbcf53809c.png

Quartz的核心是三個(gè)組件。

任務(wù):Job 用于表示被調(diào)度的任務(wù);

觸發(fā)器:Trigger 定義調(diào)度時(shí)間的元素,即按照什么時(shí)間規(guī)則去執(zhí)行任務(wù)。一個(gè)Job可以被多個(gè)Trigger關(guān)聯(lián),但是一個(gè)Trigger 只能關(guān)聯(lián)一個(gè)Job;

調(diào)度器 :工廠類(lèi)創(chuàng)建Scheduler,根據(jù)觸發(fā)器定義的時(shí)間規(guī)則調(diào)度任務(wù)。

25d59ed4-a880-11ee-8b88-92fbcf53809c.png

上圖代碼中Quartz 的JobStore是RAMJobStore,Trigger 和 Job 存儲(chǔ)在內(nèi)存中。

執(zhí)行任務(wù)調(diào)度的核心類(lèi)是QuartzSchedulerThread

25f61600-a880-11ee-8b88-92fbcf53809c.png

調(diào)度線程從JobStore中獲取需要執(zhí)行的的觸發(fā)器列表,并修改觸發(fā)器的狀態(tài);

Fire觸發(fā)器,修改觸發(fā)器信息(下次執(zhí)行觸發(fā)器的時(shí)間,以及觸發(fā)器狀態(tài)),并存儲(chǔ)起來(lái)。

最后創(chuàng)建具體的執(zhí)行任務(wù)對(duì)象,通過(guò)worker線程池執(zhí)行任務(wù)。

接下來(lái)再聊聊 Quartz 的集群部署方案。

Quartz的集群部署方案,需要針對(duì)不同的數(shù)據(jù)庫(kù)類(lèi)型(MySQL , ORACLE) 在數(shù)據(jù)庫(kù)實(shí)例上創(chuàng)建Quartz表,JobStore是: JobStoreSupport。

這種方案是分布式的,沒(méi)有負(fù)責(zé)集中管理的節(jié)點(diǎn),而是利用數(shù)據(jù)庫(kù)行級(jí)鎖的方式來(lái)實(shí)現(xiàn)集群環(huán)境下的并發(fā)控制。

scheduler實(shí)例在集群模式下首先獲取{0}LOCKS表中的行鎖,Mysql 獲取行鎖的語(yǔ)句:

2622de06-a880-11ee-8b88-92fbcf53809c.png

{0}會(huì)替換為配置文件默認(rèn)配置的QRTZ_。sched_name為應(yīng)用集群的實(shí)例名,lock_name就是行級(jí)鎖名。Quartz主要有兩個(gè)行級(jí)鎖觸發(fā)器訪問(wèn)鎖 (TRIGGER_ACCESS) 和 狀態(tài)訪問(wèn)鎖(STATE_ACCESS)。

262da1c4-a880-11ee-8b88-92fbcf53809c.png

這個(gè)架構(gòu)解決了任務(wù)的分布式調(diào)度問(wèn)題,同一個(gè)任務(wù)只能有一個(gè)節(jié)點(diǎn)運(yùn)行,其他節(jié)點(diǎn)將不執(zhí)行任務(wù),當(dāng)碰到大量短任務(wù)時(shí),各個(gè)節(jié)點(diǎn)頻繁的競(jìng)爭(zhēng)數(shù)據(jù)庫(kù)鎖,節(jié)點(diǎn)越多性能就會(huì)越差。

2 分布式鎖模式

Quartz的集群模式可以水平擴(kuò)展,也可以分布式調(diào)度,但需要業(yè)務(wù)方在數(shù)據(jù)庫(kù)中添加對(duì)應(yīng)的表,有一定的強(qiáng)侵入性。

有不少研發(fā)同學(xué)為了避免這種侵入性,也探索出分布式鎖模式。

業(yè)務(wù)場(chǎng)景:電商項(xiàng)目,用戶(hù)下單后一段時(shí)間沒(méi)有付款,系統(tǒng)就會(huì)在超時(shí)后關(guān)閉該訂單。

通常我們會(huì)做一個(gè)定時(shí)任務(wù)每?jī)煞昼妬?lái)檢查前半小時(shí)的訂單,將沒(méi)有付款的訂單列表查詢(xún)出來(lái),然后對(duì)訂單中的商品進(jìn)行庫(kù)存的恢復(fù),然后將該訂單設(shè)置為無(wú)效。

我們使用Spring Schedule的方式做一個(gè)定時(shí)任務(wù)。

@Scheduled(cron="0*/2***?")
publicvoiddoTask(){
log.info("定時(shí)任務(wù)啟動(dòng)");
//執(zhí)行關(guān)閉訂單的操作
orderService.closeExpireUnpayOrders();
log.info("定時(shí)任務(wù)結(jié)束");
}

在單服務(wù)器運(yùn)行正常,考慮到高可用,業(yè)務(wù)量激增,架構(gòu)會(huì)演進(jìn)成集群模式,在同一時(shí)刻有多個(gè)服務(wù)執(zhí)行一個(gè)定時(shí)任務(wù),有可能會(huì)導(dǎo)致業(yè)務(wù)紊亂。

解決方案是在任務(wù)執(zhí)行的時(shí)候,使用Redis 分布式鎖來(lái)解決這類(lèi)問(wèn)題。

@Scheduled(cron="0*/2***?")
publicvoiddoTask(){
log.info("定時(shí)任務(wù)啟動(dòng)");
StringlockName="closeExpireUnpayOrdersLock";
RedisLockredisLock=redisClient.getLock(lockName);
//嘗試加鎖,最多等待3秒,上鎖以后5分鐘自動(dòng)解鎖
booleanlocked=redisLock.tryLock(3,300,TimeUnit.SECONDS);
if(!locked){
log.info("沒(méi)有獲得分布式鎖:{}",lockName);
return;
}
try{
//執(zhí)行關(guān)閉訂單的操作
orderService.closeExpireUnpayOrders();
}finally{
redisLock.unlock();
}
log.info("定時(shí)任務(wù)結(jié)束");
}

263767b8-a880-11ee-8b88-92fbcf53809c.png

Redis的讀寫(xiě)性能極好,分布式鎖也比Quartz數(shù)據(jù)庫(kù)行級(jí)鎖更輕量級(jí)。當(dāng)然Redis鎖也可以替換成Zookeeper鎖,也是同樣的機(jī)制。

在小型項(xiàng)目中,使用:定時(shí)任務(wù)框架(Quartz/Spring Schedule)和 分布式鎖(redis/zookeeper)有不錯(cuò)的效果。

但是呢?我們可以發(fā)現(xiàn)這種組合有兩個(gè)問(wèn)題:

定時(shí)任務(wù)在分布式場(chǎng)景下有空跑的情況,而且任務(wù)也無(wú)法做到分片;

要想手工觸發(fā)任務(wù),必須添加額外的代碼才能完成。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

3 ElasticJob-Lite 框架

ElasticJob-Lite 定位為輕量級(jí)無(wú)中心化解決方案,使用 jar 的形式提供分布式任務(wù)的協(xié)調(diào)服務(wù)。

264c1d52-a880-11ee-8b88-92fbcf53809c.png

應(yīng)用內(nèi)部定義任務(wù)類(lèi),實(shí)現(xiàn)SimpleJob接口,編寫(xiě)自己任務(wù)的實(shí)際業(yè)務(wù)流程即可。

publicclassMyElasticJobimplementsSimpleJob{
@Override
publicvoidexecute(ShardingContextcontext){
switch(context.getShardingItem()){
case0:
//dosomethingbyshardingitem0
break;
case1:
//dosomethingbyshardingitem1
break;
case2:
//dosomethingbyshardingitem2
break;
//casen:...
}
}
}

舉例:應(yīng)用A有五個(gè)任務(wù)需要執(zhí)行,分別是A,B,C,D,E。任務(wù)E需要分成四個(gè)子任務(wù),應(yīng)用部署在兩臺(tái)機(jī)器上。

2660b3fc-a880-11ee-8b88-92fbcf53809c.png

應(yīng)用A在啟動(dòng)后, 5個(gè)任務(wù)通過(guò) Zookeeper 協(xié)調(diào)后被分配到兩臺(tái)機(jī)器上,通過(guò)Quartz Scheduler 分開(kāi)執(zhí)行不同的任務(wù)。

ElasticJob 從本質(zhì)上來(lái)講 ,底層任務(wù)調(diào)度還是通過(guò) Quartz ,相比Redis分布式鎖 或者 Quartz 分布式部署 ,它的優(yōu)勢(shì)在于可以依賴(lài) Zookeeper 這個(gè)大殺器 ,將任務(wù)通過(guò)負(fù)載均衡算法分配給應(yīng)用內(nèi)的 Quartz Scheduler容器。

從使用者的角度來(lái)講,是非常簡(jiǎn)單易用的。但從架構(gòu)來(lái)看,調(diào)度器和執(zhí)行器依然在同一個(gè)應(yīng)用方JVM內(nèi),而且容器在啟動(dòng)后,依然需要做負(fù)載均衡。應(yīng)用假如頻繁的重啟,不斷的去選主,對(duì)分片做負(fù)載均衡,這些都是相對(duì)比較的操作。

ElasticJob 的控制臺(tái)通過(guò)讀取注冊(cè)中心數(shù)據(jù)展現(xiàn)作業(yè)狀態(tài),更新注冊(cè)中心數(shù)據(jù)修改全局任務(wù)配置。從一個(gè)任務(wù)調(diào)度平臺(tái)的角度來(lái)看,控制臺(tái)功能還是偏孱弱的。

4 中心化流派

中心化的原理是:把調(diào)度和任務(wù)執(zhí)行,隔離成兩個(gè)部分:調(diào)度中心和執(zhí)行器。調(diào)度中心模塊只需要負(fù)責(zé)任務(wù)調(diào)度屬性,觸發(fā)調(diào)度命令。執(zhí)行器接收調(diào)度命令,去執(zhí)行具體的業(yè)務(wù)邏輯,而且兩者都可以進(jìn)行分布式擴(kuò)容。

4.1 MQ模式

先談?wù)勎以谒圐埓黉N(xiāo)團(tuán)隊(duì)接觸的第一種中心化架構(gòu)。

2670d570-a880-11ee-8b88-92fbcf53809c.png

調(diào)度中心依賴(lài)Quartz集群模式,當(dāng)任務(wù)調(diào)度時(shí)候,發(fā)送消息到RabbitMQ 。業(yè)務(wù)應(yīng)用收到任務(wù)消息后,消費(fèi)任務(wù)信息。

這種模型充分利用了MQ解耦的特性,調(diào)度中心發(fā)送任務(wù),應(yīng)用方作為執(zhí)行器的角色,接收任務(wù)并執(zhí)行。

但這種設(shè)計(jì)強(qiáng)依賴(lài)消息隊(duì)列,可擴(kuò)展性和功能,系統(tǒng)負(fù)載都和消息隊(duì)列有極大的關(guān)聯(lián)。這種架構(gòu)設(shè)計(jì)需要架構(gòu)師對(duì)消息隊(duì)列非常熟悉。

4.2 XXL-JOB

XXL-JOB 是一個(gè)分布式任務(wù)調(diào)度平臺(tái),其核心設(shè)計(jì)目標(biāo)是開(kāi)發(fā)迅速、學(xué)習(xí)簡(jiǎn)單、輕量級(jí)、易擴(kuò)展?,F(xiàn)已開(kāi)放源代碼并接入多家公司線上產(chǎn)品線,開(kāi)箱即用。

267d7c8a-a880-11ee-8b88-92fbcf53809c.png

xxl-job 2.3.0架構(gòu)圖

我們重點(diǎn)剖析下架構(gòu)圖 :

網(wǎng)絡(luò)通訊 server-worker 模型

269108a4-a880-11ee-8b88-92fbcf53809c.png

調(diào)度中心和執(zhí)行器 兩個(gè)模塊之間通訊是 server-worker 模式。調(diào)度中心本身就是一個(gè)SpringBoot 工程,啟動(dòng)會(huì)監(jiān)聽(tīng)8080端口

執(zhí)行器啟動(dòng)后,會(huì)啟動(dòng)內(nèi)置服務(wù)( EmbedServer )監(jiān)聽(tīng)9994端口。這樣雙方都可以給對(duì)方發(fā)送命令。

那調(diào)度中心如何知道執(zhí)行器的地址信息呢 ?上圖中,執(zhí)行器會(huì)定時(shí)發(fā)送注冊(cè)命令 ,這樣調(diào)度中心就可以獲取在線的執(zhí)行器列表。

通過(guò)執(zhí)行器列表,就可以根據(jù)任務(wù)配置的路由策略選擇節(jié)點(diǎn)執(zhí)行任務(wù)。常見(jiàn)的路由策略有如下三種:

隨機(jī)節(jié)點(diǎn)執(zhí)行:選擇集群中一個(gè)可用的執(zhí)行節(jié)點(diǎn)執(zhí)行調(diào)度任務(wù)。適用場(chǎng)景:離線訂單結(jié)算。

26af0084-a880-11ee-8b88-92fbcf53809c.png

廣播執(zhí)行:在集群中所有的執(zhí)行節(jié)點(diǎn)分發(fā)調(diào)度任務(wù)并執(zhí)行。適用場(chǎng)景:批量更新應(yīng)用本地緩存。

26b9ab9c-a880-11ee-8b88-92fbcf53809c.png

分片執(zhí)行:按照用戶(hù)自定義分片邏輯進(jìn)行拆分,分發(fā)到集群中不同節(jié)點(diǎn)并行執(zhí)行,提升資源利用效率。適用場(chǎng)景:海量日志統(tǒng)計(jì)。

26d02fac-a880-11ee-8b88-92fbcf53809c.png

▍ 調(diào)度器

調(diào)度器是任務(wù)調(diào)度系統(tǒng)里面非常核心的組件。XXL-JOB 的早期版本是依賴(lài)Quartz。

但在v2.1.0版本中完全去掉了Quartz的依賴(lài),原來(lái)需要?jiǎng)?chuàng)建的 Quartz表也替換成了自研的表。

核心的調(diào)度類(lèi)是:JobTriggerPoolHelper。調(diào)用start方法后,會(huì)啟動(dòng)兩個(gè)線程:scheduleThread 和 ringThread 。

首先 scheduleThread 會(huì)定時(shí)從數(shù)據(jù)庫(kù)加載需要調(diào)度的任務(wù),這里從本質(zhì)上還是基于數(shù)據(jù)庫(kù)行鎖保證同時(shí)只有一個(gè)調(diào)度中心節(jié)點(diǎn)觸發(fā)任務(wù)調(diào)度。

Connectionconn=XxlJobAdminConfig.getAdminConfig()
.getDataSource().getConnection();
connAutoCommit=conn.getAutoCommit();
conn.setAutoCommit(false);
preparedStatement=conn.prepareStatement(
"select*fromxxl_job_lockwherelock_name='schedule_lock'forupdate");
preparedStatement.execute();
#觸發(fā)任務(wù)調(diào)度(偽代碼)
for(XxlJobInfojobInfo:scheduleList){
//省略代碼
}
#事務(wù)提交
conn.commit();

調(diào)度線程會(huì)根據(jù)任務(wù)的「下次觸發(fā)時(shí)間」,采取不同的動(dòng)作:

26e7a7ae-a880-11ee-8b88-92fbcf53809c.png

已過(guò)期的任務(wù)需要立刻執(zhí)行的,直接放入線程池中觸發(fā)執(zhí)行 ,五秒內(nèi)需要執(zhí)行的任務(wù)放到 ringData 對(duì)象里。

ringThread 啟動(dòng)后,定時(shí)從 ringData 對(duì)象里獲取需要執(zhí)行的任務(wù)列表 ,放入到線程池中觸發(fā)執(zhí)行。

26f5b556-a880-11ee-8b88-92fbcf53809c.png

2700c2f2-a880-11ee-8b88-92fbcf53809c.png

5 自研在巨人的肩膀上

2018年,我有一段自研任務(wù)調(diào)度系統(tǒng)的經(jīng)歷。

背景是:兼容技術(shù)團(tuán)隊(duì)自研的RPC框架,技術(shù)團(tuán)隊(duì)不需要修改代碼,RPC注解方法可以托管在任務(wù)調(diào)度系統(tǒng)中,直接當(dāng)做一個(gè)任務(wù)來(lái)執(zhí)行。

自研過(guò)程中,研讀了XXL-JOB 源碼,同時(shí)從阿里云分布式任務(wù)調(diào)度 SchedulerX 吸取了很多營(yíng)養(yǎng)。

271320b4-a880-11ee-8b88-92fbcf53809c.png

SchedulerX 1.0 架構(gòu)圖

Schedulerx-console 是任務(wù)調(diào)度的控制臺(tái),用于創(chuàng)建、管理定時(shí)任務(wù)。負(fù)責(zé)數(shù)據(jù)的創(chuàng)建、修改和查詢(xún)。在產(chǎn)品內(nèi)部與 schedulerx server 交互。

Schedulerx-server 是任務(wù)調(diào)度的服務(wù)端,是 Scheduler的核心組件。負(fù)責(zé)客戶(hù)端任務(wù)的調(diào)度觸發(fā)以及任務(wù)執(zhí)行狀態(tài)的監(jiān)測(cè)。

Schedulerx-client 是任務(wù)調(diào)度的客戶(hù)端。每個(gè)接入客戶(hù)端的應(yīng)用進(jìn)程就是一個(gè)的 Worker。Worker 負(fù)責(zé)與 Schedulerx-server 建立通信,讓 schedulerx-server發(fā)現(xiàn)客戶(hù)端的機(jī)器。并向schedulerx-server注冊(cè)當(dāng)前應(yīng)用所在的分組,這樣 schedulerx-server才能向客戶(hù)端定時(shí)觸發(fā)任務(wù)。

我們模仿了SchedulerX的模塊,架構(gòu)設(shè)計(jì)如下圖:

2724bfea-a880-11ee-8b88-92fbcf53809c.png

我選擇了 RocketMQ 源碼的通訊模塊 remoting 作為自研調(diào)度系統(tǒng)的通訊框架?;谌缦聝牲c(diǎn):

我對(duì)業(yè)界大名鼎鼎的 Dubbo不熟悉,而remoting我已經(jīng)做了多個(gè)輪子,我相信自己可以搞定;

在閱讀 SchedulerX 1.0 client 源碼中,發(fā)現(xiàn) SchedulerX 的通訊框架和RocketMQ Remoting很多地方都很類(lèi)似。它的源碼里有現(xiàn)成的工程實(shí)現(xiàn),完全就是一個(gè)寶藏。

我將 RocketMQ remoting 模塊去掉名字服務(wù)代碼,做了一定程度的定制。

在RocketMQ的remoting里,服務(wù)端采用 Processor 模式。

2742008c-a880-11ee-8b88-92fbcf53809c.png

調(diào)度中心需要注冊(cè)兩個(gè)處理器:回調(diào)結(jié)果處理器CallBackProcessor和心跳處理器HeartBeatProcessor 。執(zhí)行器需要注冊(cè)觸發(fā)任務(wù)處理器TriggerTaskProcessor 。

publicvoidregisterProcessor(
intrequestCode,
NettyRequestProcessorprocessor,
ExecutorServiceexecutor);

處理器的接口:

publicinterfaceNettyRequestProcessor{
RemotingCommandprocessRequest(
ChannelHandlerContextctx,
RemotingCommandrequest)throwsException;
booleanrejectRequest();
}

對(duì)于通訊框架來(lái)講,我并不需要關(guān)注通訊細(xì)節(jié),只需要實(shí)現(xiàn)處理器接口即可。

以觸發(fā)任務(wù)處理器TriggerTaskProcessor舉例:

274fd1bc-a880-11ee-8b88-92fbcf53809c.png

搞定網(wǎng)絡(luò)通訊后,調(diào)度器如何設(shè)計(jì) ?最終我還是選擇了Quartz 集群模式。主要是基于以下幾點(diǎn)原因:

調(diào)度量不大的情況下 ,Quartz 集群模式足夠穩(wěn)定,而且可以兼容原來(lái)的XXL-JOB任務(wù);

使用時(shí)間輪的話(huà),本身沒(méi)有足夠的實(shí)踐經(jīng)驗(yàn),擔(dān)心出問(wèn)題。另外,如何讓任務(wù)通過(guò)不同的調(diào)度服務(wù)(schedule-server)觸發(fā), 需要有一個(gè)協(xié)調(diào)器。于是想到Zookeeper。但這樣的話(huà),又引入了新的組件。

研發(fā)周期不能太長(zhǎng),想快點(diǎn)出成果。

自研版的調(diào)度服務(wù)花費(fèi)一個(gè)半月上線了。系統(tǒng)運(yùn)行非常穩(wěn)定,研發(fā)團(tuán)隊(duì)接入也很順暢。調(diào)度量也不大 ,四個(gè)月總共接近4000萬(wàn)到5000萬(wàn)之間的調(diào)度量。

坦率的講,自研版的瓶頸,我的腦海里經(jīng)常能看到。數(shù)據(jù)量大,我可以搞定分庫(kù)分表,但 Quartz 集群基于行級(jí)鎖的模式 ,注定上限不會(huì)太高。

為了解除心中的困惑,我寫(xiě)一個(gè)輪子DEMO看看可否work:

去掉外置的注冊(cè)中心,調(diào)度服務(wù)(schedule-server)管理會(huì)話(huà);

引入zookeeper,通過(guò)zk協(xié)調(diào)調(diào)度服務(wù)。但是HA機(jī)制很粗糙,相當(dāng)于一個(gè)任務(wù)調(diào)度服務(wù)運(yùn)行,另一個(gè)服務(wù)standby;

Quartz 替換成時(shí)間輪 (參考Dubbo里的時(shí)間輪源碼)。

277961a8-a880-11ee-8b88-92fbcf53809c.png

這個(gè)Demo版本在開(kāi)發(fā)環(huán)境可以運(yùn)行,但有很多細(xì)節(jié)需要優(yōu)化,僅僅是個(gè)玩具,并沒(méi)有機(jī)會(huì)運(yùn)行到生產(chǎn)環(huán)境。

最近讀阿里云的一篇文章《如何通過(guò)任務(wù)調(diào)度實(shí)現(xiàn)百萬(wàn)規(guī)則報(bào)警》,SchedulerX2.0 高可用架構(gòu)見(jiàn)下圖:

278794da-a880-11ee-8b88-92fbcf53809c.jpg

文章提到:

每個(gè)應(yīng)用都會(huì)做三備份,通過(guò) zk 搶鎖,一主兩備,如果某臺(tái) Server 掛了,會(huì)進(jìn)行 failover,由其他 Server 接管調(diào)度任務(wù)。

這次自研任務(wù)調(diào)度系統(tǒng)從架構(gòu)來(lái)講,并不復(fù)雜,實(shí)現(xiàn)了XXL-JOB的核心功能,也兼容了技術(shù)團(tuán)隊(duì)的RPC框架,但并沒(méi)有實(shí)現(xiàn)工作流以及mapreduce分片。

SchedulerX 在升級(jí)到2.0之后基于全新的Akka 架構(gòu),這種架構(gòu)號(hào)稱(chēng)實(shí)現(xiàn)高性能工作流引擎,實(shí)現(xiàn)進(jìn)程間通信,減少網(wǎng)絡(luò)通訊代碼。

在我調(diào)研的開(kāi)源任務(wù)調(diào)度系統(tǒng)中,PowerJob也是基于Akka 架構(gòu),同時(shí)也實(shí)現(xiàn)了工作流和MapReduce執(zhí)行模式。

我對(duì)PowerJob非常感興趣,也會(huì)在學(xué)習(xí)實(shí)踐后輸出相關(guān)文章,敬請(qǐng)期待。

6 技術(shù)選型

首先我們將任務(wù)調(diào)度開(kāi)源產(chǎn)品和商業(yè)產(chǎn)品 SchedulerX 放在一起,生成一張對(duì)照表:

2794c6b4-a880-11ee-8b88-92fbcf53809c.png

Quartz 和 ElasticJob從本質(zhì)上還是屬于框架的層面。

中心化產(chǎn)品從架構(gòu)上來(lái)講更加清晰,調(diào)度層面更靈活,可以支持更復(fù)雜的調(diào)度(mapreduce動(dòng)態(tài)分片,工作流)。

XXL-JOB 從產(chǎn)品層面已經(jīng)做到極簡(jiǎn),開(kāi)箱即用,調(diào)度模式可以滿(mǎn)足大部分研發(fā)團(tuán)隊(duì)的需求。簡(jiǎn)單易用 + 能打,所以非常受大家歡迎。

其實(shí)每個(gè)技術(shù)團(tuán)隊(duì)的技術(shù)儲(chǔ)備不盡相同,面對(duì)的場(chǎng)景也不一樣,所以技術(shù)選型并不能一概而論。

不管是使用哪種技術(shù),在編寫(xiě)任務(wù)業(yè)務(wù)代碼時(shí),還是需要注意兩點(diǎn):

冪等。當(dāng)任務(wù)被重復(fù)執(zhí)行的時(shí)候,或者分布式鎖失效的時(shí)候,程序依然可以輸出正確的結(jié)果;

任務(wù)不跑了,千萬(wàn)別驚慌。查看調(diào)度日志,JVM層面使用Jstack命令查看堆棧,網(wǎng)絡(luò)通訊要添加超時(shí)時(shí)間 ,一般能解決大部分問(wèn)題。

7 寫(xiě)到最后

2015年其實(shí)是非常有趣的一年。ElasticJob 和 XXL-JOB 這兩種不同流派的任務(wù)調(diào)度項(xiàng)目都開(kāi)源了。

在 XXL-JOB 源碼里,至今還保留著許雪里老師在開(kāi)源中國(guó)的一條動(dòng)態(tài)截圖:

剛寫(xiě)的任務(wù)調(diào)度框架 ,Web動(dòng)態(tài)管理任務(wù),實(shí)時(shí)生效,熱乎的。沒(méi)有意外的話(huà),明天中午推送到git.osc上去。哈哈,下樓炒個(gè)面加個(gè)荷包蛋慶祝下。

看到這個(gè)截圖,內(nèi)心深處竟然會(huì)有一種共情,嘴角不自禁的上揚(yáng)。

我又想起:2016年,ElasticJob的作者張亮老師開(kāi)源了sharding-jdbc 。我在github上創(chuàng)建了一個(gè)私有項(xiàng)目,參考sharding-jdbc的源碼,自己實(shí)現(xiàn)分庫(kù)分表的功能。第一個(gè)類(lèi)名叫:ShardingDataSource,時(shí)間定格在 2016/3/29。

審核編輯:黃飛

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    12

    文章

    9160

    瀏覽量

    85419
  • 觸發(fā)器
    +關(guān)注

    關(guān)注

    14

    文章

    2000

    瀏覽量

    61155
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    809

    瀏覽量

    26568
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    158

    瀏覽量

    12226
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    375

    瀏覽量

    10875

原文標(biāo)題:任務(wù)調(diào)度系統(tǒng)就該這么設(shè)計(jì)(萬(wàn)能通用),穩(wěn)的一批!

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    STM32 簡(jiǎn)單多任務(wù)調(diào)度

    STM32的開(kāi)發(fā)目前大多數(shù)還開(kāi)處于“裸奔”的階段,處于開(kāi)發(fā)成本的考慮,可能還未嵌入任何的RTOS系統(tǒng),由于沒(méi)有操作系統(tǒng)的支持,因而不能方便的對(duì)多任務(wù)進(jìn)行調(diào)度和管理,在main函數(shù)中你可
    發(fā)表于 03-09 15:59

    【安富萊】【RTX操作系統(tǒng)教程】第10章 任務(wù)調(diào)度-搶占式,時(shí)間片和合作式

    第10章 任務(wù)調(diào)度-搶占式,時(shí)間片和合作式 本章教程為大家將介紹RTX操作系統(tǒng)支持的任務(wù)調(diào)度方式,搶占式,時(shí)間片和合作式,這部分算是RTX操
    發(fā)表于 01-25 13:57

    Spark232源碼調(diào)度系統(tǒng)Task任務(wù)提交

    Spark232源碼解析: 10 調(diào)度系統(tǒng) Task任務(wù)提交 (三) TaskSchedulerExecutor 任務(wù)提交
    發(fā)表于 04-15 10:31

    如何使用Tracealyzer理解多任務(wù)調(diào)度?

    優(yōu)先級(jí),指示任務(wù)系統(tǒng)中的緊迫性。RTOS調(diào)度器總是從當(dāng)前準(zhǔn)備執(zhí)行的就緒任務(wù)表中選擇優(yōu)先級(jí)最高的任務(wù)執(zhí)行。分配合適的
    發(fā)表于 12-17 16:01

    嵌入式系統(tǒng)任務(wù)管理與調(diào)度

    慕課電子科技大學(xué).嵌入式系統(tǒng).第七章.任務(wù)管理與調(diào)度.任務(wù)管理3-任務(wù)管理機(jī)制0 目錄7 任務(wù)
    發(fā)表于 12-21 08:00

    任務(wù)系統(tǒng)與單任務(wù)系統(tǒng)分別是指什么

    。多任務(wù)的并發(fā)執(zhí)行通常依賴(lài)于一個(gè)多任務(wù)操作系統(tǒng)(OS),多任務(wù)OS的核心系統(tǒng)
    發(fā)表于 12-22 07:20

    調(diào)度器的原理及其任務(wù)調(diào)度代碼實(shí)現(xiàn)

    一、介紹調(diào)度器是常用的一種編程框架,也是操作系統(tǒng)的拆分多任務(wù)核心,比如單片機(jī)的裸機(jī)程序框架,網(wǎng)絡(luò)協(xié)議棧的框架如can網(wǎng)關(guān)、485網(wǎng)關(guān)等等,使用場(chǎng)合比較多,是做穩(wěn)定產(chǎn)品比較常用的編程技
    發(fā)表于 02-17 07:07

    UCOSIII的任務(wù)管理與任務(wù)調(diào)度和切換簡(jiǎn)述

    UCOSIII學(xué)習(xí)筆記(二)文章目錄UCOSIII學(xué)習(xí)筆記(二)一、UCOSIII任務(wù)管理1、任務(wù)的基本概念2、UCOSIII系統(tǒng)任務(wù)3、UCOSIII的
    發(fā)表于 02-18 06:14

    VxWorks系統(tǒng)任務(wù)調(diào)度機(jī)制

    針對(duì)多任務(wù)系統(tǒng)而言,調(diào)度是指根據(jù)一定的算法.將CPU 分配給符合條件的任務(wù)使用,不同的系統(tǒng)任務(wù)
    發(fā)表于 12-16 14:11 ?10次下載

    基于模糊聚類(lèi)思想的網(wǎng)格獨(dú)立任務(wù)調(diào)度算法

    任務(wù)調(diào)度是網(wǎng)格研究的核心問(wèn)題之一,在研究網(wǎng)格任務(wù)調(diào)度問(wèn)題的基礎(chǔ)上,利用模糊聚類(lèi)思想提出將網(wǎng)格任務(wù)
    發(fā)表于 04-10 09:27 ?14次下載

    VxWorks下周期任務(wù)調(diào)度任務(wù)周期選擇

    本文介紹了VxWorks操作系統(tǒng)任務(wù)調(diào)度的策略,分析了實(shí)際設(shè)計(jì)應(yīng)用中,周期任務(wù)調(diào)度的需求。介紹了一種在VxWorks操作
    發(fā)表于 06-25 14:08 ?18次下載

    基于多Agent的維修任務(wù)調(diào)度系統(tǒng)的研究

    本文根據(jù)維修作業(yè)任務(wù)調(diào)度的復(fù)雜性,以及當(dāng)前存在的問(wèn)題,提出了基于Multi-Agent技術(shù)的維修作業(yè)任務(wù)調(diào)度系統(tǒng),建立了基于管理Agent、
    發(fā)表于 07-30 11:33 ?12次下載

    網(wǎng)格任務(wù)調(diào)度算法研究

    網(wǎng)格任務(wù)調(diào)度算法是影響網(wǎng)格成功與否的關(guān)鍵技術(shù)之一。本文總結(jié)了網(wǎng)格計(jì)算系統(tǒng)的體系結(jié)構(gòu)和特征,分析了網(wǎng)格任務(wù)調(diào)度算法的基本原理和性能指標(biāo),并對(duì)各
    發(fā)表于 08-14 10:27 ?10次下載

    VxWorks系統(tǒng)任務(wù)調(diào)度機(jī)制

    針對(duì)多任務(wù)系統(tǒng)而言,調(diào)度是指根據(jù)一定的算法.將CPU 分配給符合條件的任務(wù)使用,不同的系統(tǒng)任務(wù)
    發(fā)表于 11-27 16:26 ?13次下載

    任務(wù)調(diào)度開(kāi)源代碼是什么

    通過(guò)[嵌入式軟件架構(gòu)設(shè)計(jì)-任務(wù)調(diào)度]了解到 MCU 的三種任務(wù)調(diào)度:前后臺(tái)順序執(zhí)行法、時(shí)間片論法和操作系統(tǒng),下面介紹一個(gè)基于時(shí)間片論法的
    的頭像 發(fā)表于 02-15 14:53 ?932次閱讀