Подтвердить что ты не робот

Запустить задачу @Scheduled только в одном кластере WebLogic node?

Мы запускаем веб-приложение Spring 3.0.x(.war) с ночным заданием @Scheduled в кластерной среде WebLogic 10.3.4. Однако, когда приложение развертывается для каждого node (с помощью мастера развертывания в веб-консоли AdminServer), задание запускается каждый раз node каждую ночь, при этом выполняется несколько раз одновременно.

Как мы можем предотвратить это?

Я знаю, что такие библиотеки, как Quartz, позволяют выполнять координацию заданий внутри кластерной среды с помощью таблицы блокировки базы данных, или я мог бы даже реализовать что-то подобное. Но, поскольку это кажется довольно распространенным сценарием, мне интересно, не существует ли Spring с опцией, как легко обойти эту проблему, не добавляя в проект новые библиотеки или не применяя ручные методы обхода.

Пожалуйста, дайте мне знать, есть ли открытые вопросы. Я также задал этот вопрос на Spring форумах сообщества. Большое спасибо за вашу помощь.

4b9b3361

Ответ 1

Мы реализуем нашу собственную логику синхронизации, используя общую таблицу блокировок внутри базы данных приложения. Это позволяет всем узлам кластера проверять, запущено ли задание, прежде чем запускать его сам.

Ответ 2

У нас есть только одна задача, которая отправляет ежедневную сводную электронную почту. Чтобы избежать дополнительных зависимостей, мы просто проверяем, соответствует ли имя хоста каждому node настроенному системному свойству.

private boolean isTriggerNode() {
   String triggerHostmame = System.getProperty("trigger.hostname");;
   String hostName = InetAddress.getLocalHost().getHostName();
   return hostName.equals(triggerHostmame);
}

public void execute() {
   if (isTriggerNode()) {
      //send email
   }
}

Ответ 3

Будьте осторожны, так как в решении по внедрению собственной логики синхронизации с использованием общей таблицы блокировки всегда возникает проблема с concurrency, когда два узла кластера считывают/записывают из таблицы в одно и то же время.

Лучше всего выполнить следующие шаги в одной транзакции db: - прочитать значение в таблице общих блокировок - если никакой другой node не имеет блокировки, возьмите блокировку - обновите таблицу, указав, что вы берете блокировку

Ответ 4

Я решил эту проблему, сделав одно из ящиков мастером. в основном устанавливают переменную среды в одном из полей, например master = true.

и прочитайте его в своем java-коде через system.getenv( "master" ). если его настоящее и его истинное, тогда запустите свой код.

базовый фрагмент

@schedule()
void process(){
boolean master=Boolean.parseBoolean(system.getenv("master"));
if(master)
{
   //your logic
}

}

Ответ 5

вы можете попробовать использовать TimerManager (Планировщик заданий в кластерной среде) из WebLogic в качестве реализации TaskScheduler (TimerManagerTaskScheduler). Он должен работать в кластерной среде.

Andrea

Ответ 6

Мы можем заставить другие машины на кластере не запускать пакетное задание, используя следующую строку cron. Он не будет работать до 2099 года.

0 0 0 1 1? 2099