Quartz原理分析

一、Quartz概念

Quartz是一個(gè)優(yōu)秀的任務(wù)調(diào)度框架, 具有以下特點(diǎn):

  • 強(qiáng)大的調(diào)度功能,例如支持豐富多樣的調(diào)度方法,可以滿足各種常規(guī)及特殊需求;
  • 負(fù)載均衡
  • 高可用

調(diào)度器:scheduler

任務(wù)調(diào)度的控制器,負(fù)責(zé)定時(shí)任務(wù)的調(diào)度,并且提供任務(wù)和觸發(fā)器的增刪改查等api方法。

任務(wù):job

job是實(shí)際被調(diào)度的任務(wù),每個(gè)任務(wù)必須指定具體執(zhí)行任務(wù)的實(shí)現(xiàn)類,實(shí)現(xiàn)類需要繼承QuartzJobBean或者實(shí)現(xiàn)org.quartz.Job接口,具體的業(yè)務(wù)邏輯寫在execute方法里面。
是否支持并發(fā)的注解:@DisallowConcurrentExecution

觸發(fā)器:trigger

trigger用來定義調(diào)度時(shí)間的概念,即按什么樣時(shí)間規(guī)則去觸發(fā)任務(wù)。主要幾種類型:

  • SimpleTrigger:簡(jiǎn)單觸發(fā)器,從某個(gè)時(shí)間開始,每隔多少時(shí)間觸發(fā),重復(fù)多少次。
  • CronTrigger:使用cron表達(dá)式定義觸發(fā)的時(shí)間規(guī)則,如"0 0 0,2,4 1/1 * ? *" 表示每天的0,2,4點(diǎn)觸發(fā)。
  • DailyTimeIntervalTrigger:每天中的一個(gè)時(shí)間段,每N個(gè)時(shí)間單元觸發(fā),時(shí)間單元可以是毫秒,秒,分,小時(shí)
  • CalendarIntervalTrigger:每N個(gè)時(shí)間單元觸發(fā),時(shí)間單元可以是毫秒,秒,分,小時(shí),日,月,年。

trigger狀態(tài):
-WAITING,

  • ACQUIRED,
  • EXECUTING,
  • COMPLETE,
  • BLOCKED,
  • ERROR,
  • PAUSED,
  • PAUSED_BLOCKED,
  • DELETED
Quartz核心元素關(guān)系圖.png
Quartz線程視圖.png

Scheduler 調(diào)度線程主要有兩個(gè): 執(zhí)行常規(guī)調(diào)度的線程,和執(zhí)行 misfired trigger 的線程。常規(guī)調(diào)度線程輪詢存儲(chǔ)的所有 trigger,如果有需要觸發(fā)的 trigger,即到達(dá)了下一次觸發(fā)的時(shí)間,則從任務(wù)執(zhí)行線程池獲取一個(gè)空閑線程,執(zhí)行與該 trigger 關(guān)聯(lián)的任務(wù)。Misfire 線程是掃描所有的 trigger,查看是否有 misfired trigger,如果有的話根據(jù) misfire 的策略分別處理。

Quartz 調(diào)度線程流程圖

未正常觸發(fā)的任務(wù):misfire job

沒有在正常觸發(fā)時(shí)間點(diǎn)觸發(fā)的任務(wù)。主要由一下幾種情況導(dǎo)致:

  • 觸發(fā)時(shí)間在應(yīng)用不可用的時(shí)間內(nèi),比如重啟
  • 上次的執(zhí)行時(shí)間過長(zhǎng),超過了下次觸發(fā)的時(shí)間
  • 任務(wù)被暫停一段時(shí)間后,重新被調(diào)度的時(shí)間在下次觸發(fā)時(shí)間之后

處理misfire job的策略,需要在創(chuàng)建trigger的時(shí)候配置,每種trigger對(duì)應(yīng)的枚舉值都不同,具體在接口里面有定義。CronTrigger有2種處理misfire的策略:

處理策略 描述
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW 立即觸發(fā)一次
MISFIRE_INSTRUCTION_DO_NOTHING 忽略,不處理,等待下次觸發(fā)

之間的關(guān)系:

scheduler由工廠類SchedulerFactory創(chuàng)建,主要負(fù)責(zé)job和trigger的持久化管理,包括新增、刪除、修改、觸發(fā)、暫停、恢復(fù)調(diào)度、停止調(diào)度等;

一個(gè)job可以關(guān)聯(lián)多個(gè)trigger,但是一個(gè)trigger只能關(guān)聯(lián)一個(gè)job。

Quzrtz執(zhí)行原理

單機(jī)模式

單機(jī)模式基本使用

(TODO)

單機(jī)模式原理分析

  1. scheduler是一個(gè)計(jì)劃調(diào)度器容器(總部),容器里面可以盛放眾多的JobDetail和trigger,當(dāng)容器啟動(dòng)后,里面的每個(gè)JobDetail都會(huì)根據(jù)trigger按部就班自動(dòng)去執(zhí)行。
  2. JobDetail是一個(gè)可執(zhí)行的工作,它本身可能是有狀態(tài)的。
  3. Trigger代表一個(gè)調(diào)度參數(shù)的配置,什么時(shí)候去調(diào)。
    4.當(dāng)JobDetail和Trigger在scheduler容器上注冊(cè)后,形成了裝配好的作業(yè)(JobDetail和Trigger所組成的一對(duì)兒),就可以伴隨容器啟動(dòng)而調(diào)度執(zhí)行了。
  4. scheduler是個(gè)容器,容器中有一個(gè)線程池,用來并行調(diào)度執(zhí)行每個(gè)作業(yè),這樣可以提高容器效率。
quartz原理圖

集群模式

Quartz的集群模式指的是一個(gè)集群下多個(gè)節(jié)點(diǎn)管理同一批任務(wù)的調(diào)度,通過共享數(shù)據(jù)庫(kù)的方式實(shí)現(xiàn),保證同一個(gè)任務(wù)到達(dá)觸發(fā)時(shí)間的時(shí)候,只有一臺(tái)機(jī)器去執(zhí)行該任務(wù)。每個(gè)節(jié)點(diǎn)部署一個(gè)單獨(dú)的quartz實(shí)例,相互之間沒有直接數(shù)據(jù)通信。

集群模式基本使用

(TODO)


Quartz集群模式部署

集群模式原理分析

quartz集群是通過數(shù)據(jù)庫(kù)表來感知其他的應(yīng)用的,各個(gè)節(jié)點(diǎn)之間并沒有直接的通信。只有使用持久的JobStore才能完成Quartz集群。
數(shù)據(jù)庫(kù)表:以前有12張表,現(xiàn)在只有11張表,現(xiàn)在沒有存儲(chǔ)listener相關(guān)的表,多了QRTZ_SIMPROP_TRIGGERS表:

Table name Description
QRTZ_CALENDARS 存儲(chǔ)Quartz的Calendar信息
QRTZ_CRON_TRIGGERS 存儲(chǔ)CronTrigger,包括Cron表達(dá)式和時(shí)區(qū)信息
QRTZ_FIRED_TRIGGERS 存儲(chǔ)與已觸發(fā)的Trigger相關(guān)的狀態(tài)信息,以及相聯(lián)Job的執(zhí)行信息
QRTZ_PAUSED_TRIGGER_GRPS 存儲(chǔ)已暫停的Trigger組的信息
QRTZ_SCHEDULER_STATE 存儲(chǔ)少量的有關(guān)Scheduler的狀態(tài)信息,和別的Scheduler實(shí)例
QRTZ_LOCKS 存儲(chǔ)程序的悲觀鎖的信息
QRTZ_JOB_DETAILS 存儲(chǔ)每一個(gè)已配置的Job的詳細(xì)信息
QRTZ_SIMPLE_TRIGGERS 存儲(chǔ)簡(jiǎn)單的Trigger,包括重復(fù)次數(shù)、間隔、以及已觸的次數(shù)
QRTZ_BLOG_TRIGGERS Trigger作為Blob類型存儲(chǔ)
QRTZ_TRIGGERS 存儲(chǔ)已配置的Trigger的信息
QRTZ_SIMPROP_TRIGGERS

QRTZ_LOCKS就是Quartz集群實(shí)現(xiàn)同步機(jī)制的行鎖表,包括以下幾個(gè)鎖:

  • CALENDAR_ACCESS
  • JOB_ACCESS
  • MISFIRE_ACCESS
  • STATE_ACCESS
  • TRIGGER_ACCESS

負(fù)責(zé)任務(wù)調(diào)度的幾個(gè)線程:
(1)任務(wù)執(zhí)行線程:通常使用一個(gè)線程池(SimpleThreadPool)維護(hù)一組線程,負(fù)責(zé)實(shí)際每個(gè)job的執(zhí)行。
(2)Scheduler調(diào)度線程QuartzSchedulerThread :輪詢存儲(chǔ)的所有 trigger,如果有需要觸發(fā)的 trigger,即到達(dá)了下一次觸發(fā)的時(shí)間,則從任務(wù)執(zhí)行線程池獲取一個(gè)空閑線程,執(zhí)行與該 trigger 關(guān)聯(lián)的任務(wù)。
(3)處理misfire job的線程MisfireHandler:輪訓(xùn)所有misfire的trigger,原理就是從數(shù)據(jù)庫(kù)中查詢所有下次觸發(fā)時(shí)間小于當(dāng)前時(shí)間的trigger,按照每個(gè)trigger設(shè)定的misfire策略處理這些trigger。

參考資料

  1. Quartz集群原理分析
  2. 深入解讀Quartz的原理
  3. quartz (從原理到應(yīng)用)詳解篇
  4. 美團(tuán)技術(shù)團(tuán)隊(duì) Quartz應(yīng)用與集群原理分析
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容