Quartz框架(四)—misfire處理機制

Quartz框架(一)—Quartz的基本配置
Quartz框架(二)—jobstore數據庫表字段詳解
Quartz框架(三)—任務的並行/串行執行

什麼叫做misfire

在Quartz中,當一個持久化的觸發器因爲:
1. 調度器被關閉;
2. 線程池沒有可用線程;
3. 項目重啓;
4. 任務的串行執行;
而錯過激活時間,就會發生激活失敗(misfire)。

此時我們需要明確兩個問題(1)如何判定激活失敗;(2)如何處理激活失敗;

1. 如何判定激活失敗

Quartz框架(一)—Quartz的基本配置中,quartz.properties配置文件中含有一個屬性是misfireThreshold(單位毫秒),用來指定調度引擎設置觸發器超時的“臨界值”。也就是說Quartz對於任務的超時是有容忍度的。只有超過這個容忍度纔會判定位misfire。

quartz.properties的配置文件

#設置容忍度爲12s
org.quartz.jobStore.misfireThreshold = 12000

Corn=[*/2 * * * * ?] 即每兩秒循環一次

jobDetail每次執行需要7s

@Component
@DisallowConcurrentExecution
public class TestJob2 extends  CustomQuartzJobBean{
    private Logger logger = LoggerFactory.getLogger(TestJob2.class);

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        logger.info("【數據庫配置定時】-【開始】");
        try {
            Thread.sleep(7000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("【數據庫配置定時】-【結束】");
    }
}
任務編號 預定運行時刻 實際運行時刻 延遲量(秒)
1 17:54:00 17:54:00 0
2 17:54:02 17:54:07 5
3 17:54:04 17:54:14 10
4 17:54:06 17:54:21 misfire

從表中可以看到,每一次任務的延遲都是5s作用,該延遲量不斷累積,並且與misfireThreshold比較,直到在17:54:21時發生了misfire,那麼17:54:21第4次任務會不會執行呢,答案是不一定的,取決於配置。

2. 激活失敗的處理

激活失敗指令(Misfire Instruction[因死抓可神 指令])是觸發器的一個重要配置。所有類型的觸發器都有一個默認的指令:

Trigger.MISFIRE_INSTRUCTION_SMART_POLICY

但是這個“機智策略(policy [跑了誰] )”對於不同類型的觸發器其具體行爲是不同的。

misfire Instruction在qutz_triggers表中的字段。

代碼中設置misfire策略的方式。

2.1 quartz中CornTrigger使用的策略

//所有的misfile任務馬上執行
public static final int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1;
//在Trigger中默認選擇MISFIRE_INSTRUCTION_FIRE_ONCE_NOW 策略
public static final int MISFIRE_INSTRUCTION_SMART_POLICY = 0;
// CornTrigger默認策略,合併部分misfire,正常執行下一個週期的任務。
public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1;
//所有的misFire都不管,執行下一個週期的任務。
public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2;
  • 可以通過setMisfireInstruction方法設置misfire策略。
 CronTriggerFactoryBean triggerFactoryBean = new CronTriggerFactoryBean();
 triggerFactoryBean.setName("corn_" + clazzName);
 triggerFactoryBean.setJobDetail(jobFactory.getObject());
 triggerFactoryBean.setCronExpression(quartzCorn);
 triggerFactoryBean.setGroup(QUARTZ_TRIGGER_GROUP);
 //設置misfire策略
 triggerFactoryBean.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY);
 triggerFactoryBean.afterPropertiesSet();
  • 也可以通過CronScheduleBuilder設置misfire策略。
 CronScheduleBuilder csb = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
 //MISFIRE_INSTRUCTION_DO_NOTHING
 csb.withMisfireHandlingInstructionDoNothing();
 //MISFIRE_INSTRUCTION_FIRE_ONCE_NOW
 csb.withMisfireHandlingInstructionFireAndProceed();//(默認)
 //MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY
 csb.withMisfireHandlingInstructionIgnoreMisfires();

策略的具體含義

前提:在每個星期週一下午5點到7點,每隔一個小時執行一次,理論上共執行3次。

//所有misfire的任務會馬上執行【字面意思:忽略misfire政策】
public static final int MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY = -1;

若是5點misfire,6:15系統恢復之後,5,6點的misfire會馬上執行。

//不做任何事情
public static final int MISFIRE_INSTRUCTION_DO_NOTHING = 2;

若是5點misfire,6:15系統恢復之後,只會執行7點的misfire。如果下次執行時間超過了end time,實際上就沒有執行機會了。

// CornTrigger默認策略,合併部分misfire,正常執行下一個週期的任務。
public static final int MISFIRE_INSTRUCTION_FIRE_ONCE_NOW = 1;

若是5點misfire,6:15系統恢復之後,立刻執行一次(只會一次)misfire。

2.2 quartz中SImpleTrigger使用的策略

  1. 若是使用MISFIRE_INSTRUCTION_SMART_POLICY—機智的策略

    • 如果Repeat=0; 【重複0次】
      instruction selected = MISFIRE_INSTRUCTION_FIRE_NOW;【立刻執行,對於不會重複執行的任務,只是默認的處理策略。】
    • 如果Repeat Count=REPEAT_INDEFINITELY;【無限重複】
      instruction selected = MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT;【在下一個激活點執行,且錯過的執行機會作廢。】
    • 如果Repeat Count>0;【有限重複】
      instruction selected = MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT;【立即執行,並執行指定的次數。】

文章參考

Quartz的misfire處理機制分析

任務框架quartz的misfire理解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章