石英触发器不会立即触发

Quartz trigger does not fire immediately

我想使用 jdbc 数据存储使用 quartz 调度程序立即执行作业。但是,即使我使用 now() 或调用 triggerJob 进行调度,我在调度和触发触发之间也有 20-30 秒的延迟。

我试着用一个简单的触发器来执行作业:

JobKey key = //...
        JobDetail jobDetail = newJob(jobBean.getClass())
                .withIdentity(key)
                .usingJobData(new JobDataMap(jobParams))
                .storeDurably()
                .build();

        Trigger trigger = newTrigger()
                .withIdentity(key.getName(), key.getGroup())
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withMisfireHandlingInstructionFireNow()
                        .withRepeatCount(0))
                .build();

        scheduler.scheduleJob(jobDetail, trigger);

而且我还尝试用调度程序触发:

 JobKey key = // ...
        JobDetail jobDetail = newJob(jobBean.getClass())
                .withIdentity(key)
                .storeDurably()
                .build();
        scheduler.addJob(jobDetail, true);


        scheduler.triggerJob(key, new JobDataMap(jobParams));

这是显示延迟的侦听器日志。

2019-05-15 13:59:52,066Z  INFO  [nio-8081-exec-2] c.m.f.s.logger.SchedulingListener                  : Job added: newsJobTemplate:1557928791965
2019-05-15 13:59:52,066Z  INFO  [nio-8081-exec-2] c.m.f.s.logger.SchedulingListener                  : Job scheduled: newsJobTemplate:1557928791965
2019-05-15 14:00:18,660Z  INFO  [eduler_Worker-1] c.m.f.s.logger.TriggerStateListener                : Trigger fired: QUARTZ_JOBS.newsJobTemplate:1557928791965 {}
2019-05-15 14:00:18,703Z  INFO  [eduler_Worker-1] c.m.f.s.logger.JobExecutionListener                : Job will be executed: QUARTZ_JOBS.newsJobTemplate:1557928791965
2019-05-15 14:00:19,284Z  INFO  [eduler_Worker-1] c.m.f.s.logger.JobExecutionListener                : Job was executed: QUARTZ_JOBS.newsJobTemplate:1557928791965

我发现到处都是碎屑,表明问题与交易有关。 所以我从服务方法中删除了@Transactional,瞧,它起作用了。 看起来当您调用触发器时,调度程序线程异步尝试从数据库中查找计划和触发器,但当时未提交事务。稍后调度程序线程再次查找数据库并最终找到它。

zolee 的回答完美地描述了这个问题,但也有一些事情可以解决。

一个不完美的解决方案是减少 org.quartz.scheduler.idleWaitTime。事实上,问题本身在 quartz configuration doc、org.quartz.scheduler.idleWaitTime 部分进行了描述,尽管有些隐晦。

Normally you should not have to ‘tune’ this parameter, unless you’re using XA transactions, and are having problems with delayed firings of triggers that should fire immediately.

这将使您可以将 30 秒的延迟减少到 5 秒甚至更少。

一个完整的解决方案是扩展 QuartzScheduler 以添加事务支持。确切的实施将取决于 library/code 您用于事务支持的内容,但它对我们来说非常有效。

class TransactionAwareScheduler extends QuartzScheduler {
    @Override
    protected void notifySchedulerThread(long candidateNewNextFireTime) {
        if (insideTransaction) {
            transaction.addCommitHook(() -> {
                super.notifySchedulerThread(candidateNewNextFireTime);
            });
        }
    } else {
        super.notifySchedulerThread(candidateNewNextFireTime);
    }
}