Планирование весенних загрузочных задач

1 min


Введение

Планирование задач, которые будут выполняться позднее или повторяться через фиксированный интервал, является очень полезной функцией. Например, системы или задачи новостной рассылки, которые обрабатывают информацию в установленные сроки, рассчитаны на выполнение в определенные моменты времени.

Поскольку Spring Boot предлагает несколько вариантов, мы собираемся охватить и реализовать все из них.

Настройка проекта

Как обычно, когда речь идет о создании приложений Spring Boot, создание каркасного проекта проще всего с помощью Весенний инициализр, Вам не нужно никаких дополнительных зависимостей, чтобы включить планирование.

Чтобы включить планирование, все, что нам нужно сделать, это аннотировать наш основной класс:

@SpringBootApplication
@EnableScheduling
public class SampleScheduleApplication {
    public static void main(String() args) {
        SpringApplication.run(SampleScheduleApplication.class, args);
    }
}

@EnableScheduling аннотация позволяет контейнеру Spring замечать любые @Scheduled аннотации в бинах, управляемых Spring.

Условное планирование

Есть еще один способ включить планирование – с помощью @ConditionalOnProperty аннотаций. Это позволяет нам «включать» и «выключать» наши классы конфигурации, устанавливая свойство в application.properties класс.

Чтобы сделать это, давайте создадим новый класс и аннотируем его как @EnableScheduling, @Configuration а также @ConditionalOnProperty аннотации:

@EnableScheduling
@Configuration
@ConditionalOnProperty(name = "spring.enable.scheduling")
public class ScheduleEnabling {}

Теперь в application.properties файл, давайте добавим наше новое свойство и установите его true:

spring.enable.scheduling = true

Просто сдвигая эту переменную, мы можем включать и выключать функциональность.

Чтобы выполнить метод по расписанию, необходимо аннотировать его @Scheduled аннотаций. Изменение параметров аннотации будет определять, будет ли она фиксированной, с фиксированной задержкой, пользовательскими интервалами и т. Д.

Планирование с фиксированная ставка а также fixedRateString

Чтобы запланировать выполнение метода по фиксированной ставке, мы добавим соответствующий параметр в нашу аннотацию: @Scheduled(fixedRate), Этот параметр принимает целые числа, выраженные в миллисекундах. Таким образом, если вы хотите скорость в 1 секунду, скорость должна быть введена как 1000 так как значение составляет миллисекунды.

Кроме того, вы можете использовать @Scheduled(fixedRateString) параметр для вывода суммы с помощью строковой переменной среды.

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

Давайте установим переменную в application.properties файл:

sample.schedule.string = PT2S

Префикс PT является стандартом ISO-8601 для отмечая продолжительность или периодыи с этим мы можем назвать sample.schedule.string запланировать вызов метода за 2 секунды.

Это также позволяет нам указать разные задержки для разных используемых профилей:

@Scheduled(fixedRateString = "${sample.schedule.string}")
public void scheduleTaskWithFixedRate() throws InterruptedException {
    task1();
    task2();
}

public void task1() throws InterruptedException {
    logger.info("Task 1 starts" + Thread.currentThread());
    Thread.sleep(1000);
    logger.info("Task 1 ends" + Thread.currentThread());
}

public void task2() throws InterruptedException {
    logger.info("Task 2 starts" + Thread.currentThread());
    Thread.sleep(1000);
    logger.info("Task 2 ends" + Thread.currentThread());
}

Давайте запустим этот кусок кода:

Планирование с фиксированной ставкой

Тем не менее, мы можем увидеть проблему здесь:

Задание 1 начинается в 00:01:44 и заканчивается в 00:01:45, как и ожидалось.
Задание 2 начинается в 00:01:45 и заканчивается в 00:01:46, как и ожидалось.
Задание 1 начинается в 00:01:46 и заканчивается в 00:01:47.

Поскольку оба task1() а также task2() Если вы были выполнены, вы ожидаете, что метод будет ждать еще 2 секунды для повторного запуска.

Задачи с фиксированной скоростью не ждут завершения предыдущего выполнения, они просто вызывают метод с определенной скоростью. Поскольку для завершения методов требуется 2 секунды task1() а также task2(), метод вызывается снова в то же время, когда эти два завершаются.

Это может стать проблемой в среде с несколькими запланированными задачами.

Учти это – task1() занимает 1 минуту, и task2() занимает 5 секунд, чтобы завершить. Поскольку оба они работают в одном потоке, может возникнуть ситуация, когда task1() начинает обработку и заблокирует поток. Это не позволит task2() обрабатывать, даже если есть fixedRate 5 секунд.

В этом случае нам нужно увеличить количество потоков, доступных в нашем пуле потоков для планирования. Spring предоставляет свойство, которым мы можем манипулировать, чтобы указать размер: spring.task.scheduling.pool.size – значение по умолчанию равно 1.

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

Планирование с fixedDelay а также fixedDelayString

fixedDelay работает очень похоже на fixedRate, Но разница здесь в том, что фиксированная задержка ждет до завершения предыдущего выполнения, чтобы начать следующее. Представьте себе сценарий, в котором вашей функции требуется 1 секунда, чтобы завершить выполнение, и вы дали фиксированную задержку в 2 секунды.

Это, в свою очередь, приведет в общей сложности к 3 секундам.

В журналах ниже вы можете ясно видеть, что разница между двумя последующими задачами составляет 3 секунды. Это включает в себя фиксированное время задержки в 1 секунду, а также 2 секунды, которые мы дали как сон:

@Scheduled(fixedDelayString = "${sample.schedule.string}")
public void scheduleTaskWithFixedDelay() throws InterruptedException {
    task1();
}

public void task1() throws InterruptedException {
    logger.info("Task 1 starts" + Thread.currentThread());
    Thread.sleep(1000);
    logger.info("Task 1 ends" + Thread.currentThread());
}

Давайте запустим этот кусок кода:

Планирование с фиксированной задержкой

Есть дополнительный параметр, который можно добавить к запланированным задачам, и это initialDelay,

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

Если у вас есть функция с начальной задержкой в ​​2 секунды и фиксированной скоростью в 1 секунду, то первое выполнение будет отложено на 2 секунды, а затем функция будет выполняться каждые 1 секунду:

@Scheduled(initialDelay = 1000, fixedRateString = "${sample.schedule.string}")
public void scheduleTaskWithInitialDelay() throws InterruptedException {
    task1();
}

Мы также можем использовать initialDelayString это позволяет нам выводить значение задержки.

Пользовательские интервалы времени

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

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

Cron Expressions

Большинство разработчиков, вероятно, слышали о хрон Утилита в Linux. Это процесс-демон, который выполняется без вмешательства пользователя и выполняет задачи.

Синтаксис выражений cron в cron Утилита и синтаксис для выражений cron для планирования в основном похожи.

Выражения Cron – это в основном строки, которые описывают детали расписания. Это обеспечивает намного больше контроля, чем предыдущие 2 метода:

имя необходимые Допустимые значения Разрешенные специальные символы
секунд да 0-59 , - * /
минут да 0-59 , - * /
часов да 0-23 , - * /
День месяца да 1-31 , - * / L W C
Месяц да 0-11 или Январь , - * /
День недели да 1-7 или ВС-САТ , - * / L C #
Год нет пустой или 1970-2099 , - * /

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

Выражения Cron могут быть очень простыми, но также и очень сложными. Ясное понимание ценностей облегчит игру с ними.

За исключением поля год, все остальные поля являются обязательными:

      

Пример: 0 0 12 * * ? 2019 – Это выражение cron срабатывает в 12 часов дня, каждого дня месяца, каждого месяца, за 2019 год.

Для некоторых распространенных значений вы также можете использовать предопределенные аннотации:

  • @reboot: Запланируйте метод для каждой перезагрузки приложения
  • @yearly/@anually: Запланируйте запуск метода один раз в год
  • @monthly: Запланируйте запуск метода один раз в месяц
  • @weekly: Запланируйте запуск метода раз в неделю
  • @daily/@midnight: Запланируйте запуск метода один раз в день
  • @hourly: Запланируйте запуск метода один раз в час

Давайте напишем пример кода для этого:

@Scheduled(cron="0 0 12 * * ? 2019")
public void doSomething() {
    // Something
}

При планировании важно помнить о часовых поясах – проклятии каждого разработчика, который работает со временем.

Вы, вероятно, захотите установить zone флаг определенного региона. Например, мы будем запускать этот метод в 12:00 каждый день в 2019 году, основываясь на часовом поясе Парижа:

@Scheduled(cron="0 0 12 * * ? 2019", zone="Europe/Paris")
public void doSomething() {
    // Something
}

Вы можете найти все часовые пояса на официальные документы Oracle,

Конечно, вы также можете выводить выражения cron через application.properties файл:

cron.expression= 0 0 12 * * ? 2019

И затем вызвать его через:

@Scheduled(cron="${cron.expression}", zone="Europe/Paris")
public void doSomething() {
    // Something
}

Вы также можете использовать сайт, как FreeFormatter создать выражение cron, установив входные параметры. Это очень полезно для новичков в создании выражений cron.

Заключение

В этой статье мы увидели, как мы можем планировать задачи с помощью Spring Boot. Самым большим преимуществом использования Spring Boot является простота, с которой мы можем реализовать планирование. Мало того, он также предлагает несколько вариантов, чтобы мы могли выбрать то, что соответствует нашим требованиям.

Планировщики являются важными компонентами большинства приложений, потому что они отправляют критичную по времени, а также специфичную для пользователя информацию по мере необходимости. Теперь ты знаешь как!


0 Comments

Ваш e-mail не будет опубликован. Обязательные поля помечены *