2016-09-24 3 views
3

Я подозреваю, что проблема заключается в том, что набор SchedulerFactoryBeanOverwriteExistingJobs не обеспечивает достаточной защиты.Состояние расы планировщика весеннего кварца

Один узел будет инициализации планировщика и примет решение заменить триггер (контрольная точка 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 и только после того, как он выполняет, запустить второй сервер, и вы получите это исключение

Во всяком случае, мне удалось получить эту ошибку локально, а после примерно 4 0 передислоцируется на локальный кластерный веб-сервер.

ответ

1

Проблема заключается в том, что по умолчанию диспетчер транзакций не используется, поэтому блокировка не используется.

Чтобы решить проблему, необходимо вызвать метод setTransactionManager schedulerFactoryBean.