避免与石英失火

时间:2015-08-18 14:23:10

标签: java quartz-scheduler

我在使用Quartz时遇到了一个痛苦的问题并且失误了。

我的应用程序创建允许用户创建CronTrigger和SimpleTrigger作业。

每个作业都可以暂停/恢复(使用Scheduler.pauseJob和Scheduler.resumeJob)

调度程序本身可以设置为待机状态。

我们想放弃任何失误:

  • 当调度程序处于待机状态时
  • 暂停工作时
  • 当应用程序停止时

正如此博文http://www.nurkiewicz.com/2012/04/quartz-scheduler-misfire-instructions.html中所述,我已尝试

  • withMisfireHandlingInstruction对CronTrigger没有任何政策
  • withMisfireHandlingInstructionNextWithRemainingCount for SimpleTrigger

但没有人可以放弃失火。

我目前在作业执行方法中使用了一种丑陋的解决方法:

public void execute(JobExecutionContext context) throws JobExecutionException {
    Date dateNow = new Date();
    long diff = dateNow.getTime() - context.getScheduledFireTime().getTime();
    if (diff > 500)
    {
         //its a misfire
         return;
    }

    /* rest of job execution code */

当scheduledFireTime比现在早了500多秒时,丢弃它。

但似乎有时,在生产中,这允许执行一些作业(据报道,当重新启动应用程序时会发生这种情况)

这可能吗? 有什么好办法可以避免失火吗?

Quartz版本:2.1.7(在Spring 3.2.5应用程序中)

quartz.properties

org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.dataSource=psqldatasource
org.quartz.dataSource.psqldatasource.driver=${db.driver}
org.quartz.dataSource.psqldatasource.URL=${db.url}
org.quartz.dataSource.psqldatasource.user=${db.usr}
org.quartz.dataSource.psqldatasource.password=${db.pwd}
org.quartz.threadPool.threadCount = 3

org.quartz.jobStore.useProperties = false
org.quartz.jobStore.driverDelegateClass =  org.quartz.impl.jdbcjobstore.PostgreSQLDelegate

对于Cron:

 JobDetail job = JobBuilder.newJob(JobLauncher.class)
 .withIdentity(jobIdentifierBean.getNameJob(), jobIdentifierBean.getNameGroup())
 .usingJobData(...) //defining some jobData key/values
 .build();

 Trigger trigger = TriggerBuilder.newTrigger()
 .withIdentity(name, group)
 .startNow()
 .withSchedule(CronScheduleBuilder.cronSchedule(strCronExpression).withMisfireHandlingInstructionDoNothing())
 .build();

 try {
    scheduler.scheduleJob(job, trigger);
} catch (SchedulerException e) {
    throw e;
}

for SimpleTrigger(作业定义为cron案例)

    //avoid first fire
    GregorianCalendar g = new GregorianCalendar();
    switch (enumDelayUnits) {
        case Days:
            g.add(GregorianCalendar.HOUR, delay * 24);
            break;
        case Hours:
            g.add(GregorianCalendar.HOUR, delay);
            break;
        case Minutes:
            g.add(GregorianCalendar.MINUTE, delay);
            break;
        case Seconds:
            g.add(GregorianCalendar.SECOND, delay);
            break;
        default:
            throw new ServiceException("Unknow delay type");
    }

    Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity(jobIdentifierBean.getNameTrigger(), jobIdentifierBean.getNameGroup())
            .startAt(g.getTime())
            .withSchedule(getSimpleScheduleBuilder(delay, enumDelayUnits, repeatForever))
            .build();
    try {
        scheduler.scheduleJob(job, trigger);
    } catch (SchedulerException e) {
        throw e;
    }

private SimpleScheduleBuilder getSimpleScheduleBuilder(int delay, EnumDelayUnits enumDelayType, boolean repeatForever) throws ServiceException, Exception
{
    SimpleScheduleBuilder simpleScheduleBuilder;

    simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
    switch (enumDelayType) {
    case Days:
        simpleScheduleBuilder.withIntervalInHours(24 * delay);
        break;
    case Hours:
        simpleScheduleBuilder.withIntervalInHours(delay);
        break;
    case Minutes:
        simpleScheduleBuilder.withIntervalInMinutes(delay);
        break;
    case Seconds:
        simpleScheduleBuilder.withIntervalInSeconds(delay);
        break;
    default:
        serviceError("Unknown delay " + enumDelayType);
    }
    if(repeatForever)
    {
        simpleScheduleBuilder.repeatForever();
    }

    simpleScheduleBuilder = simpleScheduleBuilder.withMisfireHandlingInstructionNextWithRemainingCount();

    return simpleScheduleBuilder;
}

1 个答案:

答案 0 :(得分:3)

我不确定你是否想过这个问题,但是我遇到了类似的问题,我的解决方案与" misfireThreshold"相关。在我的配置中:

quartz.jobStore.misfireThreshold

我的设置为60000(也就是1分钟),所以在重新启动我的日程安排服务时,如果他们在一段时间内#34;迟到",他们仍然会执行。