Ответ 1
Мы реализуем нашу собственную логику синхронизации, используя общую таблицу блокировок внутри базы данных приложения. Это позволяет всем узлам кластера проверять, запущено ли задание, прежде чем запускать его сам.
Мы запускаем веб-приложение Spring 3.0.x(.war) с ночным заданием @Scheduled в кластерной среде WebLogic 10.3.4. Однако, когда приложение развертывается для каждого node (с помощью мастера развертывания в веб-консоли AdminServer), задание запускается каждый раз node каждую ночь, при этом выполняется несколько раз одновременно.
Как мы можем предотвратить это?
Я знаю, что такие библиотеки, как Quartz, позволяют выполнять координацию заданий внутри кластерной среды с помощью таблицы блокировки базы данных, или я мог бы даже реализовать что-то подобное. Но, поскольку это кажется довольно распространенным сценарием, мне интересно, не существует ли Spring с опцией, как легко обойти эту проблему, не добавляя в проект новые библиотеки или не применяя ручные методы обхода.
Пожалуйста, дайте мне знать, есть ли открытые вопросы. Я также задал этот вопрос на Spring форумах сообщества. Большое спасибо за вашу помощь.
Мы реализуем нашу собственную логику синхронизации, используя общую таблицу блокировок внутри базы данных приложения. Это позволяет всем узлам кластера проверять, запущено ли задание, прежде чем запускать его сам.
У нас есть только одна задача, которая отправляет ежедневную сводную электронную почту. Чтобы избежать дополнительных зависимостей, мы просто проверяем, соответствует ли имя хоста каждому 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
}
}
Будьте осторожны, так как в решении по внедрению собственной логики синхронизации с использованием общей таблицы блокировки всегда возникает проблема с concurrency, когда два узла кластера считывают/записывают из таблицы в одно и то же время.
Лучше всего выполнить следующие шаги в одной транзакции db: - прочитать значение в таблице общих блокировок - если никакой другой node не имеет блокировки, возьмите блокировку - обновите таблицу, указав, что вы берете блокировку
Я решил эту проблему, сделав одно из ящиков мастером. в основном устанавливают переменную среды в одном из полей, например master = true.
и прочитайте его в своем java-коде через system.getenv( "master" ). если его настоящее и его истинное, тогда запустите свой код.
базовый фрагмент
@schedule()
void process(){
boolean master=Boolean.parseBoolean(system.getenv("master"));
if(master)
{
//your logic
}
}
вы можете попробовать использовать TimerManager (Планировщик заданий в кластерной среде) из WebLogic в качестве реализации TaskScheduler (TimerManagerTaskScheduler). Он должен работать в кластерной среде.
Andrea
Мы можем заставить другие машины на кластере не запускать пакетное задание, используя следующую строку cron. Он не будет работать до 2099 года.
0 0 0 1 1? 2099