Не стартуют задания quartz в кластерном режиме

Добрый день. Проблема следующего характера
Есть 3 сервера. 2 dev и 1 stage, на которых работает одна и та же версия приложения.

Все они работают в kubernetes с настройками:

spring.quartz.properties.org.quartz.scheduler.instanceId: “AUTO”
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass: “org.quartz.impl.jdbcjobstore.PostgreSQLDelegate”
spring.quartz.properties.org.quartz.jobStore.useProperties: “true”
spring.quartz.properties.org.quartz.jobStore.misfireThreshold: “60000”
spring.quartz.properties.org.quartz.jobStore.tablePrefix: “QRTZ_”
spring.quartz.properties.org.quartz.jobStore.isClustered: “true”
spring.quartz.properties.org.quartz.jobStore.clusterCheckinInterval: “20000”

На 2 дев-машинах задания работают без остановки согласно заданному периоду, а на stage задания работают в пределах получаса, затем не стартуют согласно следующему времени запуска, это время не меняется и выполнение заданий прерывается.

При этом, в таблице в таблице qrtz_triggers почти у всех заданий в столбце trigger_state = ERROR

То есть при абсолютно одинаковых настройках сред приложения на одном из стендов имеется проблема с запуском заданий. На первых двух работает 3 экземпляра приложения (3 pod’а), на stage работало тоже 3, сейчас 1, но ситуация не поменялась.
Иногда после ручного запуска задание стартует 1 раз и все.

Подскажите, пожалуйста, что можно проверить и как искать “корень” проблемы?

Добрый день, Иван.

Часто причиной невозможности работы задания является недоступность по какой-то причине класса задания, в котором описана его логика. Задание не может быть инициировано и лежит мертвым.

Прошу уточнить следующие моменты:

  • Все классы заданий доступны на всех pod’ах.
  • “задания работают в пределах получаса …”
    • Имеется в виду, что есть какой-то период времени, когда джобы успешно работают (т.е. стартуют и завершаются без проблем. Многократно, если джоба “частая”), но в какой-то момент во время выполнения падает и больше не стартует?
    • Или же имеется в виду, что джоба стартует впервые после старта сервера, работает какое-то продолжительное время в рамках одного запуска (джоба “долгая”) и падает, не совершив ни одного успешного выполнения?
    • И этот сценарий выполняется каждый раз после рестарта сервера?
  • Какая у вас версия Jmix?

Нужно понять, что вызывает падение задания.

Для мониторинга стоит создать листенер:

  • Spring-бин, наследник JobListenerSupport
  • Переопределите у него методы jobToBeExecuted и jobWasExecuted
    • jobToBeExecuted - срабатывает в момент запуска. Залогируйте JobKey, TriggerKey и SchedulerInstanceId. Это все можно достать из JobExecutionContext, который приходит в данный метод.
    • jobWasExecuted - срабатывает в момент завершения. Залогируйте то же самое + exception, который тоже приходит в данный метод (если что-то произошло).
@Component
public class JobExecutionMonitoringListener extends JobListenerSupport {

    private static final Logger log = LoggerFactory.getLogger(JobExecutionMonitoringListener.class);

    @Autowired
    private Scheduler scheduler;

    @Override
    public String getName() {
        return "JobExecutionMonitoringListener";
    }

    @PostConstruct
    private void registerListener() {
        try {
            scheduler.getListenerManager().addJobListener(this);
        } catch (SchedulerException e) {
            log.error("Cannot register job listener", e);
        }
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        JobKey jobKey = context.getJobDetail().getKey();
        TriggerKey triggerKey = context.getTrigger().getKey();
        String schedulerInstanceId;
        try {
            schedulerInstanceId = context.getScheduler().getSchedulerInstanceId();
        } catch (SchedulerException e) {
            schedulerInstanceId = "Unable to resolve";
        }

        log.info("Start job: Job={}, Trigger={}, Instance={}", jobKey, triggerKey, schedulerInstanceId);
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context,
                               JobExecutionException jobException) {
        JobKey jobKey = context.getJobDetail().getKey();
        TriggerKey triggerKey = context.getTrigger().getKey();
        String schedulerInstanceId;
        try {
            schedulerInstanceId = context.getScheduler().getSchedulerInstanceId();
        } catch (SchedulerException e) {
            schedulerInstanceId = "Unable to resolve";
        }

        if (jobException == null) {
            log.info("Finish job: Job={}, Trigger={}, Instance={}", jobKey, triggerKey, schedulerInstanceId);
        } else {
            log.error("Finish job with exception: Job={}, Trigger={}, Instance={}", jobKey, triggerKey, schedulerInstanceId, jobException);
        }
    }
}

Узнав причину, попробуем ее решить.

С уважением,
Иван