? ? ? ? ?ElasticJob 社區(qū)在經(jīng)過之前幾年的停滯狀況之后并入到apache迄本,并且作為 Apache ShardingSphere 的子項(xiàng)目繼續(xù)發(fā)光發(fā)熱杂腰,終于迎來了它的3.0時(shí)代,作為一個(gè)老碼農(nóng)我也趕緊跟著時(shí)代的腳本铺敌,進(jìn)行了一次深入學(xué)習(xí)和研究,這里記錄下學(xué)習(xí)筆記。
首先elasticjob底層還是基于quartz實(shí)現(xiàn)的历等,熟悉quartz的朋友都知道quartz有三個(gè)非常重要的概念:
1、scheduler是一個(gè)計(jì)劃調(diào)度器容器辟癌,容器里面可以有眾多的JobDetail和trigger寒屯,當(dāng)容器啟動后,里面的每個(gè)JobDetail都會根據(jù)trigger按部就班自動去執(zhí)行黍少。
2寡夹、JobDetail是一個(gè)可執(zhí)行的工作,它本身可能是有狀態(tài)的厂置。
3菩掏、Trigger代表一個(gè)調(diào)度參數(shù)的配置,什么時(shí)候去調(diào)昵济。
當(dāng)JobDetail和Trigger在scheduler容器上注冊后智绸,形成了裝配好的作業(yè)(JobDetail和Trigger所組成的一對兒)野揪,就可以伴隨容器啟動而調(diào)度執(zhí)行了。
scheduler是個(gè)容器传于,容器中有一個(gè)線程池囱挑,用來并行調(diào)度執(zhí)行每個(gè)作業(yè),這樣可以提高容器效率沼溜。
elasticjob3.0.0相較之前不同之處
1平挑、通過閱讀官網(wǎng)發(fā)現(xiàn)elasticjob3.0.0新增了http類型的作業(yè),可以直接調(diào)用http請求系草,并在請求頭中將分片上下文以json串的形式傳遞通熄,同時(shí)也增加了HttpJobExecutor來支撐HttpJob的執(zhí)行
我們看看官網(wǎng)上的一段代碼
文檔關(guān)于這部分的介紹就寥寥數(shù)筆,沒有寫得很細(xì)致找都。
不過通過自己寫個(gè)demo來體驗(yàn)再加上結(jié)合之前用ElasitcJob的經(jīng)驗(yàn)仔細(xì)想想唇辨,個(gè)人總結(jié)了一下這樣做的好處:之前都是將job任務(wù)處理的核心邏輯集中在job服務(wù)本身,job不僅要負(fù)責(zé)調(diào)度還需要處理核心業(yè)務(wù)邏輯能耻,這樣做之后job服務(wù)本身只需關(guān)注任務(wù)的調(diào)度和管理赏枚,核心邏輯可以分離到其他服務(wù)中去,有助于縷清微服務(wù)盛行的當(dāng)下業(yè)務(wù)邊界問題同時(shí)減少job服務(wù)本身的壓力晓猛。
2饿幅、job監(jiān)聽器采用SPI的方式由ElasticJobServiceLoader來進(jìn)行加載和管理
再來看官網(wǎng)上的一段代碼
上面就調(diào)用了ScheduleJobBootstrap類的schedule()方法,job的啟動就是從這里開始的戒职,我們看看這個(gè)方法
繼續(xù)跟進(jìn)去發(fā)現(xiàn)是調(diào)用了JobScheduleController的scheduleJob(String corn)方法
發(fā)現(xiàn)調(diào)用了scheduler的start方法栗恩,而scheduler是quartz的任務(wù)調(diào)度器,到這里就接上了quartz的任務(wù)調(diào)度過程洪燥,有沒有瞬間就懂了磕秤?
接下來我們關(guān)注下job的線程池,查看了下demo在執(zhí)行job的調(diào)用棧
關(guān)注一下SimpleThreadpool捧韵,QuartzSchedulerThread市咆,JobRunShell,LiteJob這4個(gè)類
其中QuartzSchedulerThread是一個(gè)線程類纫版,負(fù)責(zé)查詢并觸發(fā)Triggers床绪,該線程類的主要工作分為以下幾個(gè)步驟:
1、等待QuartzScheduler啟動
2其弊、查詢待觸發(fā)的Trigger
3癞己、等待Trigger觸發(fā)時(shí)間到來
4、觸發(fā)Trigger
5梭伐、循環(huán)上述步驟
具體的源碼我將在單獨(dú)的文章中進(jìn)行解析痹雅,這里不再展開。
在底部發(fā)現(xiàn)由quartz的SimpleThreadpool拉起的糊识,而這個(gè)線程池是由StdSchedulerFactory完成初始化的
看下StdSchedulerFactory的instantiate()方法绩社,SimpleThreadpool和QuartzSchedulerThread都是這個(gè)方法中初始化的
可以看到QuartzScheduler構(gòu)造方法中初始化了QuartzSchedulerThread并在線程池中啟動
我們看下QuartzSchedulerThread的run方法
這里getThreadPool獲取的線程池就是前面所述的 SimpleThreadPool摔蓝,調(diào)用runInThread方法傳入JobRunShell線程對象,并將JobRunShell賦值給SimpleThreadPool內(nèi)部類定義的工作線程 愉耙,進(jìn)入runInThread方法之后啟動了SimpleThreadPool內(nèi)部類定義的工作線程?
在WorkThread的run方法中調(diào)用了JobRunShell的run方法贮尉,
這里的job就是LiteJob
這里實(shí)際上調(diào)用的是ElasticJobExecutor的execute方法,進(jìn)入到方法里面
1朴沿、檢查job執(zhí)行環(huán)境
2猜谚、job執(zhí)行前的處理
3、正常執(zhí)行job
4赌渣、如果發(fā)生misfire則執(zhí)行job
5魏铅、job執(zhí)行后的處理
這里2和5就是調(diào)用ElasticJobListener進(jìn)行處理的,經(jīng)過輪詢監(jiān)聽器然后調(diào)用對應(yīng)的方法跟進(jìn)execute方法最后發(fā)現(xiàn)調(diào)用的是JobItemExecutor.process方法 坚芜,那前面我們知道有 SimpleJob览芳、DataFlowJob、ScriptJob鸿竖、HttpJob四種不同類型的作業(yè)沧竟,這個(gè)方法是怎么處理這四種不同的作業(yè)的呢?然后JobItemExecutor也是elasitcJob提供的一個(gè)接口缚忧,也是采用SPI的方式進(jìn)行擴(kuò)展的 屯仗,根據(jù)不同的job類型加載不同的作業(yè)處理器進(jìn)行對應(yīng)作業(yè)的處理,我們來看看它的類結(jié)構(gòu)
有興趣的同學(xué)可以看看對應(yīng)的job處理器是怎么處理作業(yè)的搔谴,這里就不再展開了。