一挽拂、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:簡單觸發(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
Scheduler 調(diào)度線程主要有兩個(gè): 執(zhí)行常規(guī)調(diào)度的線程,和執(zhí)行 misfired trigger 的線程梳猪。常規(guī)調(diào)度線程輪詢存儲的所有 trigger,如果有需要觸發(fā)的 trigger蒸痹,即到達(dá)了下一次觸發(fā)的時(shí)間春弥,則從任務(wù)執(zhí)行線程池獲取一個(gè)空閑線程,執(zhí)行與該 trigger 關(guān)聯(lián)的任務(wù)叠荠。Misfire 線程是掃描所有的 trigger匿沛,查看是否有 misfired trigger,如果有的話根據(jù) misfire 的策略分別處理榛鼎。
未正常觸發(fā)的任務(wù):misfire job
沒有在正常觸發(fā)時(shí)間點(diǎn)觸發(fā)的任務(wù)逃呼。主要由一下幾種情況導(dǎo)致:
- 觸發(fā)時(shí)間在應(yīng)用不可用的時(shí)間內(nèi),比如重啟
- 上次的執(zhí)行時(shí)間過長者娱,超過了下次觸發(fā)的時(shí)間
- 任務(wù)被暫停一段時(shí)間后抡笼,重新被調(diào)度的時(shí)間在下次觸發(fā)時(shí)間之后
處理misfire job的策略,需要在創(chuàng)建trigger的時(shí)候配置黄鳍,每種trigger對應(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ī)模式原理分析
- scheduler是一個(gè)計(jì)劃調(diào)度器容器(總部)奈嘿,容器里面可以盛放眾多的JobDetail和trigger貌虾,當(dāng)容器啟動(dòng)后,里面的每個(gè)JobDetail都會(huì)根據(jù)trigger按部就班自動(dòng)去執(zhí)行裙犹。
- JobDetail是一個(gè)可執(zhí)行的工作尽狠,它本身可能是有狀態(tài)的。
- Trigger代表一個(gè)調(diào)度參數(shù)的配置叶圃,什么時(shí)候去調(diào)袄膏。
4.當(dāng)JobDetail和Trigger在scheduler容器上注冊后,形成了裝配好的作業(yè)(JobDetail和Trigger所組成的一對兒)掺冠,就可以伴隨容器啟動(dòng)而調(diào)度執(zhí)行了沉馆。 - scheduler是個(gè)容器,容器中有一個(gè)線程池德崭,用來并行調(diào)度執(zhí)行每個(gè)作業(yè)斥黑,這樣可以提高容器效率。
集群模式
Quartz的集群模式指的是一個(gè)集群下多個(gè)節(jié)點(diǎn)管理同一批任務(wù)的調(diào)度眉厨,通過共享數(shù)據(jù)庫的方式實(shí)現(xiàn)锌奴,保證同一個(gè)任務(wù)到達(dá)觸發(fā)時(shí)間的時(shí)候氛什,只有一臺機(jī)器去執(zhí)行該任務(wù)然低。每個(gè)節(jié)點(diǎn)部署一個(gè)單獨(dú)的quartz實(shí)例,相互之間沒有直接數(shù)據(jù)通信检柬。
集群模式基本使用
(TODO)
集群模式原理分析
quartz集群是通過數(shù)據(jù)庫表來感知其他的應(yīng)用的服球,各個(gè)節(jié)點(diǎn)之間并沒有直接的通信茴恰。只有使用持久的JobStore才能完成Quartz集群。
數(shù)據(jù)庫表:以前有12張表斩熊,現(xiàn)在只有11張表琐簇,現(xiàn)在沒有存儲listener相關(guān)的表,多了QRTZ_SIMPROP_TRIGGERS表:
Table name | Description |
---|---|
QRTZ_CALENDARS | 存儲Quartz的Calendar信息 |
QRTZ_CRON_TRIGGERS | 存儲CronTrigger座享,包括Cron表達(dá)式和時(shí)區(qū)信息 |
QRTZ_FIRED_TRIGGERS | 存儲與已觸發(fā)的Trigger相關(guān)的狀態(tài)信息婉商,以及相聯(lián)Job的執(zhí)行信息 |
QRTZ_PAUSED_TRIGGER_GRPS | 存儲已暫停的Trigger組的信息 |
QRTZ_SCHEDULER_STATE | 存儲少量的有關(guān)Scheduler的狀態(tài)信息,和別的Scheduler實(shí)例 |
QRTZ_LOCKS | 存儲程序的悲觀鎖的信息 |
QRTZ_JOB_DETAILS | 存儲每一個(gè)已配置的Job的詳細(xì)信息 |
QRTZ_SIMPLE_TRIGGERS | 存儲簡單的Trigger渣叛,包括重復(fù)次數(shù)丈秩、間隔、以及已觸的次數(shù) |
QRTZ_BLOG_TRIGGERS | Trigger作為Blob類型存儲 |
QRTZ_TRIGGERS | 存儲已配置的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 :輪詢存儲的所有 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ù)庫中查詢所有下次觸發(fā)時(shí)間小于當(dāng)前時(shí)間的trigger渡嚣,按照每個(gè)trigger設(shè)定的misfire策略處理這些trigger。