当前位置: 首页 > 知识库问答 >
问题:

避免石英失火

罗晨
2023-03-14

我面临着石英和缺火的痛苦问题。

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

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

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

我们希望放弃任何缺火:

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

正如在这篇博文中所解释的http://www.nurkiewicz.com/2012/04/quartz-scheduler-misfire-instructions.html,我试过了

  • 使用MisfireHandling指令为CronTrigger启用初始化策略
  • 使用缺火处理说明,然后使用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 */

当ScheduledFitime比现在早500毫秒以上时,放弃它。

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

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

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

石英属性

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

对于克朗:

 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;
}

对于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个答案

梁豪
2023-03-14

我不确定你是否想通了这个问题,但我有一个类似的问题,对我来说,解决方案与我配置中的“misfire Threshold”有关:

quartz.jobStore.misfireThreshold

我的设置为60000(也就是1分钟),因此在重新启动我的调度服务时,如果他们在“迟到”一分钟之内,他们仍然会执行

 类似资料:
  • 问题内容: 假设我以这种方式配置了一个触发器: 触发器必须与另一个应用程序连接,并且如果存在任何问题(例如连接失败),则触发器应每10分钟重试任务五次,直到成功为止。有什么方法可以配置触发器使其工作? 问题答案: 来源 :自动重试Quartz中失败的作业 如果您想要一项不断尝试直到成功的工作,您要做的就是抛出一个带有标志的JobExecutionException,以通知调度程序在失败时再次触发它

  • 问题内容: 似乎Quartz Scheduler每秒可以运行的作业数量受到限制。在我们的方案中,我们每秒大约有20个作业,可以进行24x7的启动,而石英可以很好地完成每秒10个作业(对于JDBC支持的JobStore,它具有100个石英线程和100个数据库连接池大小),但是,当我们将其增加到20个时每秒的作业数量,石英变得非常非常慢,与实际的计划时间相比,石英的触发作业非常晚,从而导致许多失火,并

  • 我正在使用带有TerracottaJobStore Class的石英调度程序来每5分钟调度一次作业。我的工作配置是: 组织。石英jobStore。class=org。陶土。石英EnterpriseTerracottaJobStore组织。石英jobStore。tcconfig=localhost:9510 org。石英线程池。线程数=25 我有一个附加了5000个触发器的单个作业,然后该作业被安排

  • 问题内容: 有没有办法将石英作为基础调度程序? 我可以想到两件事,但都需要做一些工作: 创建一个将解析注解并注册石英作业的自定义 实施委托石英的工具。 问题是:以上两个选项是否已经编写过,是否还有另一个选项? 问题答案: 我最终制作了自己的弹簧石英“桥”。我打算建议将其作为春季的改进。 首先,我创建了一个新注释,该注释将放置在实现quartz Job接口的类上: (请注意原型作用域-石英假定每个作

  • 谢谢你的帮助!

  • 我正在使用和Quartz Grails插件2.0.13构建一个应用程序,有一些旧作业我将它们迁移到我的新应用程序,它们以前工作正常,但是现在我在尝试从页面手动运行它们时收到以下错误,在创建新作业并尝试手动运行它后也会收到相同的错误。知道可能导致此错误的原因以及如何解决它吗? 以下是我的工作示例: