在生产环境中间歇性地在预定时间触发 Quartz 作业触发器未命中

Quartz job trigger miss at scheduled time intermittently in prod environment

我已经通过 Whosebug 和许多其他网站回答了很多问题,但仍然没有找到解决我的问题的运气。

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

我们使用的是 quartz 版本 2.2.3 和 spring 批处理版本 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);
}

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

我们在作业编辑功能中将 misfire 指令更新为 2 时遇到了代码问题。我们通过将 qrtz_triggers table 中的 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 后,由于智能策略(默认),一旦负载降低,石英会在 3-5 分钟内启动误触发的作业。