Потенциальная проблема со службами cron в Beanstalk заключается в том, что заданная запланированная команда может быть вызвана более чем одной службой, если приложение выполняется более чем в одном экземпляре.Необходима координация между работающими экземплярами Tomcat, чтобы гарантировать, что задания выполняются только одним, и что, если один из них умрет, служба cron не будет прервана.
Как я это реализую, выглядит так:
- Упакуйте задание cron "config file" с WAR.Этот файл должен содержать частоты и URL-адреса (поскольку каждый действительный cron является просто вызовом определенного URL-адреса, как это делает AE)
- Использовать одну таблицу базы данных для поддержания координации.Требуется как минимум два столбца.
- первичный или уникальный ключ, который (строка) содержит команду вместе с ее частотой.(например, "@daily http://your -app / some / cron / handler / url ")
- второй столбец, который содержит время последнего выполнения.
каждый экземпляр tomcat будет запускать поток cron, который должен считывать конфигурацию из WAR и планировать свой режим ожидания столько времени, сколько потребуется до следующего вызова службы.как только время истекает, экземпляр должен сначала попытаться «потребовать» вызов, сначала выбрав из базы данных время последнего вызова этой команды, а затем обновив его, чтобы получить «блокировку».
query(SELECT last_execution_time FROM crontable WHERE command = ?)
if(NOW() - last_execution_time < reasonable window) skip;
query(UPDATE crontable SET last_execution_time = NOW() WHERE command = ? AND last_execution_time = ?)
if(number of rows updated == 0) skip;
run task()
Ключевым элементом здесь является то, что мы также включаем last_execution_time
в предложение WHERE, гарантируя, что, если какой-то другой экземпляр обновит его между нашими SELECT и UPDATE, обновление вернет, что строки не были затронуты иэтот экземпляр пропустит выполнение этой задачи.