首页 > 解决方案 > 在 prod 环境中间歇性地在预定时间错过 Quartz 作业触发器

问题描述

我已经通过 stackoverflow 和许多其他网站提出了许多问题,但仍然没有找到任何运气来解决我的问题。

我们在上午 9:30 至 10 点之间安排了大约 35 个作业,但有时 3 到 5 个作业错过了执行,并且在运行丢失的作业后,Adhoc 运行系统从第二天开始再次正常工作。这种情况会在几天或几周后再次发生。

我们正在使用石英版本 2.2.3 和弹簧批处理版本 4.2.0.RELEASE。

我们没有覆盖调度程序线程数,因为它在很长一段时间内都可以正常工作,并且突然开始间歇性地导致某些作业失败。

以下是石英属性,

<property name="quartzProperties">
    <props>
        <prop key="org.quartz.scheduler.skipUpdateCheck">true</prop>
        <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
        <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
        <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
        <prop key="org.quartz.jobStore.useProperties">false</prop>
        <prop key="org.quartz.jobStore.tablePrefix">#{'${db.defaultschema}' != '' ? '${db.defaultschema}'+'.QRTZ_' : 'QRTZ_'}</prop>
        <prop key="org.quartz.jobStore.selectWithLockSQL">SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?</prop>
        <prop key="org.quartz.jobStore.isClustered">true</prop>
        <prop key="org.quartz.jobStore.dataSource">dataSource</prop>
        <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
        </prop>
    </props>
</property>

Spring批处理作业配置:

<batch:job id="reportJob">
    <batch:step id="step1">
        <batch:tasklet>
            <batch:chunk reader="reports-reader" processor="reports-processor"
                writer="reports-writer" commit-interval="0">
            </batch:chunk>
        </batch:tasklet>
    </batch:step>
    <batch:listeners>
        <batch:listener ref="batchJobListener" />
    </batch:listeners>
</batch:job>
<bean id="reports-reader" scope="step"
    class="com.company.reportloader.reader.ReportsItemReader">
    <property name="reportsItemReaderService" ref="reportsItemReaderService"></property>
</bean>

<bean id="reports-processor" class="com.company.reportloader.processor.ReportsItemProcessor"></bean>
<bean id="reports-writer" class="com.company.reportloader.writer.ReportsItemWriter">
</bean>

覆盖 QuartzJobBean 的 executeInternal 并创建 jobParameters 来调用 spring 批处理作业,如下所示,

@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
  launcher.run(job, jobParameters);
}

任何帮助或指针都会有很大帮助。

标签: javaspring-batchscheduled-tasksquartz-schedulercrontrigger

解决方案


我们有一个代码问题,我们在作业编辑功能中将失火指令更新为 2。我们通过将 qrtz_triggers 表中的 misfire_instr 设置为 0 解决了这个问题。调度程序以某种方式认为很少有作业被误触发,因此作业没有在预定时间触发。对于下面的 cron-trigger 是 misfire 指令的定义,

**smart policy - default**  See: withMisfireHandlingInstructionFireAndProceed

**withMisfireHandlingInstructionIgnoreMisfires**
MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICYQTZ-283    All misfired executions are 
immediately executed, then the trigger runs back on schedule.
Example scenario: the executions scheduled at 9 and 10 AM are executed immediately. 
The next scheduled execution (at 11 AM) runs on time.

**withMisfireHandlingInstructionFireAndProceed**
MISFIRE_INSTRUCTION_FIRE_ONCE_NOW   Immediately executes first misfired execution and 
discards other (i.e. all misfired executions are merged together). Then back to 
schedule. No matter how many trigger executions were missed, only single immediate 
execution is performed.
Example scenario: the executions scheduled at 9 and 10 AM are merged and executed only 
once (in other words: the execution scheduled at 10 AM is discarded). The next 
scheduled execution (at 11 AM) runs on time.

**withMisfireHandlingInstructionDoNothing**
MISFIRE_INSTRUCTION_DO_NOTHING    All misfired executions are discarded, the scheduler 
simply waits for next scheduled time.
Example scenario: the executions scheduled at 9 and 10 AM are discarded, so basically 
nothing happens. The next scheduled execution (at 11 AM) runs on time.

将 misfire_instr 更新为 0 后,由于智能策略(默认),一旦负载减少,quartz 会在 3-5 分钟内启动错误触发的作业。


推荐阅读