2013-09-29 6 views
5

У меня есть настройка Spring @Scheduled с выражением cron для каждого часа, как показано ниже, где trend.olap.local.loading.cron.expression - 0 0 * * * ?.Задача Spring's @Scheduled cron запускает несколько миллисекунд до запланированного времени

@Scheduled(cron = "${trend.olap.local.loading.cron.expression}") 
public void loadHoulyDataToLocalOlap() { 
    try { 
     // To calculate prev hour; 
     Calendar cal = Calendar.getInstance(); 
     cal.add(Calendar.HOUR, -1); 
     Date date = cal.getTime(); 
     int hour = cal.get(Calendar.HOUR_OF_DAY); 
     if (LOGGER.isDebugEnabled()) { 
      LOGGER.debug("Loading hourly data into local olap :" + date 
        + ", and hour :" + hour); 
     } 

     dataIntegrationProcessor.loadHourlyDataToLocalOlap(hour); 

     if (LOGGER.isDebugEnabled()) { 
      LOGGER.debug("Loading hourly data into local olap :" + date 
        + ", and hour :" + hour + " Completed."); 
     } 
    } catch (Exception e) { 
     LOGGER.error("Error occured at loadHoulyDataToLocalOlap", e); 
    } 
} 

Здесь я намерен принять значение часа с текущей даты и времени и передать его методам исполнителя.

В основном я беру текущий час минус один, так что в 17:00, час значение должно быть 16.

Но если вы видите, журналы, час значение 15. Это происходит потому, что планировщик побежал около 16: 59: 59,831. См. Журналы log4j ниже. Похоже, что задание cron округляет миллисекунды и срабатывает за несколько миллисекунд до 17: 00: 00 000.

Из-за этого, я получаю неправильные значения, и мой деловой случай терпит неудачу.

Как сделать запуск cron ровно в нулевые миллисекунды на каждый час, а не на несколько миллисекунд раньше?

DEBUG 2013-09-29 16:59:59,831 (TrendScheduler.java loadHoulyDataToLocalOlap:57) - Loading hourly data into local olap :Sun Sep 29 15:59:59 IST 2013, and hour :15 
DEBUG 2013-09-29 16:59:59,831 (DataIntegrationProcessor.java loadHourlyDataToLocalOlap:57) - Loading hourly data for hour :15 
INFO 2013-09-29 17:00:00,054 (KettleJobExecutor.java executeJob:73) - Job (24hr_populate_hour_data_job.kjb) executed successfully 
DEBUG 2013-09-29 17:00:00,054 (TrendScheduler.java loadHoulyDataToLocalOlap:64) - Loading hourly data into local olap :Sun Sep 29 15:59:59 IST 2013, and hour :15 Completed. 
+0

Одним из решений является установка метода Thread.sleep (1000) внутри loadHoulyDataToLocalOlap() в начале. Есть ли лучшее решение, чем это? – PShetty

ответ

3

Короткий ответ в том, что вы не можете с опцией cron. Разрешение выражений cron равно второму, так что оно будет округлено до ближайшей секунды. Возможно, вы сможете гарантировать, что это произойдет, по крайней мере, через определенное время, но не точно на нем с помощью cron.

Ваш лучший выбор - реализовать свои собственные Trigger. Интерфейс Trigger имеет единственный метод, который возвращает java.util.Date для следующего выполнения (который находится в миллисекундах). Оттуда вы можете зарегистрировать задачу и выполнить триггер, как показано в документации: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableScheduling.html

0

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

У вас есть два варианта: 1. Запустите задание cron через несколько секунд после часа. 2. Измените свой расчет часа, чтобы начать работу с начала.

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

1

Если вы намерены вставить правильное значение часа, я думаю, что лучшим решением будет вычисление часа на основе менее прогнозируемого графика cron. Пока он подпадает под секунду, вы можете просто получить текущее время и преобразовать его в ближайший час, а затем получить значение часа оттуда. Вы также можете добавить предупреждения/предупреждения, чтобы узнать, работает ли cron неустойчиво, прослушивая задачи, которые начинаются более чем на минуту позже или опоздали на 10 минут и т. Д.

Хотя вы можете настроить расписание cron вместо этого, Я чувствую, что это скорее взлом, чем обращение с ним в коде, поскольку вы приближаетесь к приближению в этот момент. У вас больше контроля над кодом, чтобы обрабатывать более чем сто миллисекундное смещение