Я подозреваю, что проблема заключается в том, что setOverwriteExistingJobs SchedulerFactoryBean не обеспечивает достаточной защиты.
Один узел будет инициализировать планировщик и решит заменить триггер (точка останова org.quartz.impl.jdbcjobstore.SimpleTriggerPersistenceDelegate#deleteExtendedTriggerProperties )
Сразу после выполнения этого метода триггер больше не будет находиться в базе данных, поэтому, когда другой узел в кластере попытается прочитать его (org.quartz.impl.jdbcjobstore.JobStoreSupport#retrieveTrigger), произойдет сбой с исключением ниже . Из-за этого исключения не запустится все приложение (не только планировщик).
Причина: org.quartz.JobPersistenceException: не удалось получить триггер: не найдена запись для выбора триггера с ключом:
Журналы можно найти по адресу https://github.com/apixandru/case-study/tree/master/spring-boot-quartz/logs (Исключение можно найти на узле Сервер-1 после 4-го рестарта)
Для просмотра всего проекта, демонстрирующего эту проблему, перейдите по адресу 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 и сразу после его выполнения запустите второй сервер, и вы получите это исключение.
Во всяком случае, мне удалось получить эту ошибку локально после примерно 40 повторных развертываний на мой локальный кластерный сервер weblogic.