【问题标题】:Spring Quartz Scheduler race conditionSpring Quartz Scheduler 竞争条件
【发布时间】:2017-02-02 01:40:25
【问题描述】:

我怀疑问题出在 SchedulerFactoryBean 的 setOverwriteExistingJobs 没有提供足够的保护。

一个节点将初始化调度程序并决定替换触发器(断点 org.quartz.impl.jdbcjobstore.SimpleTriggerPersistenceDelegate#deleteExtendedTriggerProperties)

在执行此方法后,触发器将不再存在于数据库中,因此当集群中的另一个节点尝试读取它时(org.quartz.impl.jdbcjobstore.JobStoreSupport#retrieveTrigger),它将失败并显示下面的例外。由于这个异常,整个应用程序将无法启动(不仅仅是调度程序)。

原因:org.quartz.JobPersistenceException:无法检索 trigger: 没有找到用于选择 Trigger with key 的记录:

日志可以在https://github.com/apixandru/case-study/tree/master/spring-boot-quartz/logs找到 (第4次重启后Server-1节点可以发现异常)

对于演示此问题的整个项目,请转到 https://github.com/apixandru/case-study/tree/master/spring-boot-quartz

我们配置调度器的方式在这里

@Bean
JobDetailFactoryBean jobFactoryBean() {
    JobDetailFactoryBean bean = new JobDetailFactoryBean();
    bean.setDurability(true);
    bean.setName("Sampler");
    bean.setJobClass(SampleJob.class);
    return bean;
}

@Bean
SimpleTriggerFactoryBean triggerFactoryBean(JobDetailFactoryBean jobFactoryBean) {
    SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
    bean.setName("Sampler Trigger");
    bean.setRepeatInterval(20_000);
    bean.setJobDetail(jobFactoryBean.getObject());
    return bean;
}

@Bean
SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean triggerFactoryBean, DataSource dataSource, Dependency dependency) {
    Properties props = new Properties();
    props.put("org.quartz.scheduler.instanceId", "AUTO");
    props.put("org.quartz.jobStore.isClustered", "true");

    SchedulerFactoryBean bean = new SchedulerFactoryBean();
    bean.setTriggers(triggerFactoryBean.getObject());
    bean.setSchedulerName("Demo Scheduler");
    bean.setSchedulerContextAsMap(Collections.singletonMap("dependency", dependency));
    bean.setOverwriteExistingJobs(true);
    bean.setDataSource(dataSource);
    bean.setQuartzProperties(props);

    return bean;
}

这在我们的工作服务器上经常发生,但要在本地获取要困难得多(可能是因为实际的服务器是专用的并且比我的本地计算机具有更多的功率?)

要在任何机器上获取错误,请在调试模式下启动一个服务器并在 SimpleTriggerPersistenceDelegate.deleteExtendedTriggerProperties 上放置一个断点,然后在它执行后,启动第二个服务器,您将得到此异常

无论如何,在我重新部署到本地集群 weblogic 服务器大约 40 次后,我也设法在本地得到了这个错误。

【问题讨论】:

    标签: java spring spring-boot scheduled-tasks quartz-scheduler


    【解决方案1】:

    问题在于默认情况下不使用事务管理器,因此不使用锁定。

    要解决这个问题,需要调用 schedulerFactoryBean 的 setTransactionManager 方法。

    【讨论】:

    • 你有没有示例代码? @Alexandru
    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多