Quartz任务调度中Misfire处理机制详解
问题背景
在Quartz调度框架中,当任务被暂停后重新启动时,被暂停期间积压的任务会连续多次调用job中的execute方法。如果任务处理时间过长,会导致系统资源紧张甚至崩溃。
Misfire机制解析
CronTrigger处理规则
指令 | 行为描述 |
---|---|
withMisfireHandlingInstructionDoNothing | 不立即触发执行,等待下次Cron触发时刻按正常频率执行 |
withMisfireHandlingInstructionIgnoreMisfires | 立即从第一个错过的时间点开始执行,补做所有错过周期后恢复正常频率 |
withMisfireHandlingInstructionFireAndProceed | 立即以当前时间触发一次,然后按正常Cron频率执行 |
SimpleTrigger处理规则
指令 | 行为描述 |
---|---|
withMisfireHandlingInstructionFireNow | 立即执行,完成剩余周期次数 |
withMisfireHandlingInstructionIgnoreMisfires | 从第一个错过时间点开始补做所有周期 |
withMisfireHandlingInstructionNextWithExistingCount | 不立即执行,等待下次触发时刻完成剩余次数 |
withMisfireHandlingInstructionNowWithExistingCount | 立即执行完成剩余次数 |
withMisfireHandlingInstructionNextWithRemainingCount | 不立即执行,等待下次触发完成剩余次数 |
withMisfireHandlingInstructionNowWithRemainingCount | 立即执行完成剩余次数 |
解决方案
配置调整
在quartz.properties
中添加:
# 设置misfire阈值(毫秒),超过此值将不处理misfire
org.quartz.jobStore.misfireThreshold = 5000
```java
public String add() throws IOException, SchedulerException {
String cronExp = job.getCronExpression();
Scheduler scheduler = schedulerFactoryBean.getScheduler();
TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (null == trigger) {
// 新建任务
JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class)
.withIdentity(job.getJobName(), job.getJobGroup()).build();
jobDetail.getJobDataMap().put("scheduleJob", job);
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule(job.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
trigger = TriggerBuilder.newTrigger()
.withIdentity(job.getJobName(), job.getJobGroup())
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
} else {
// 更新现有任务
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
.cronSchedule(job.getCronExpression())
.withMisfireHandlingInstructionDoNothing();
trigger = trigger.getTriggerBuilder()
.withIdentity(triggerKey)
.withSchedule(scheduleBuilder).build();
scheduler.rescheduleJob(triggerKey, trigger);
}
return SUCCESS;
}