1. Обзор
В этом руководстве мы рассмотрим распределенное планирование и обработку фоновых заданий в Java с помощью JobRunr и интегрируем его со Spring.
2. О JobRunr
JobRunr — это библиотека, которую мы можем встроить в наше приложение и которая позволяет нам планировать фоновые задания с помощью лямбда-выражения Java 8. Мы можем использовать любой существующий метод наших сервисов Spring для создания задания без необходимости реализации интерфейса. Задание может быть коротким или длительным процессом, и оно будет автоматически перенесено в фоновый поток, чтобы текущий веб-запрос не блокировался.
Для выполнения своей работы JobRunr анализирует лямбду Java 8. Он сериализует его как JSON и сохраняет либо в реляционной базе данных, либо в хранилище данных NoSQL.
3. Возможности JobRunr
Если мы видим, что мы производим слишком много фоновых заданий и наш сервер не справляется с нагрузкой, мы можем легко масштабироваться по горизонтали , просто добавляя дополнительные экземпляры нашего приложения. JobRunr автоматически распределяет нагрузку и распределяет все задания по разным экземплярам нашего приложения.
Он также содержит функцию автоматического повтора с экспоненциальной политикой отсрочки для невыполненных заданий. Существует также встроенная панель инструментов , которая позволяет нам отслеживать все рабочие места. JobRunr является самообслуживаемым — успешно выполненные задания будут автоматически удаляться по истечении заданного периода времени, поэтому нет необходимости выполнять ручную очистку хранилища.
4. Настройка
Для простоты мы будем использовать хранилище данных в памяти для хранения всей информации, связанной с работой.
4.1. Конфигурация Maven
Давайте сразу перейдем к коду Java. Но перед этим нам нужно объявить следующую зависимость Maven в нашем файле pom.xml
:
<dependency>
<groupId>org.jobrunr</groupId>
<artifactId>jobrunr-spring-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
4.2. Весенняя интеграция
Прежде чем мы перейдем непосредственно к созданию фоновых заданий, нам нужно инициализировать JobRunr. Поскольку мы используем зависимость jobrunr-spring-boot-starter
, это легко сделать. Нам нужно только добавить некоторые свойства в application.properties
:
org.jobrunr.background-job-server.enabled=true
org.jobrunr.dashboard.enabled=true
Первое свойство сообщает JobRunr, что мы хотим запустить экземпляр BackgroundJobServer
, который отвечает за обработку заданий. Второе свойство указывает JobRunr запустить встроенную панель мониторинга.
По умолчанию jobrunr-spring-boot-starter
попытается использовать ваш существующий источник
данных в случае реляционной базы данных для хранения всей информации, связанной с заданием.
Однако, поскольку мы будем использовать хранилище данных в памяти, нам необходимо предоставить bean-компонент StorageProvider
:
@Bean
public StorageProvider storageProvider(JobMapper jobMapper) {
InMemoryStorageProvider storageProvider = new InMemoryStorageProvider();
storageProvider.setJobMapper(jobMapper);
return storageProvider;
}
5. Использование
Теперь давайте узнаем, как создавать и планировать фоновые задания в Spring с помощью JobRunr.
5.1. Внедрить зависимости
Когда мы хотим создавать задания, нам нужно внедрить JobScheduler
и нашу существующую службу Spring, содержащую метод, для которого мы хотим создать задания, в данном случае SampleJobService
:
@Inject
private JobScheduler jobScheduler;
@Inject
private SampleJobService sampleJobService;
Класс JobScheduler
из JobRunr позволяет нам ставить в очередь или планировать новые фоновые задания.
SampleJobService может
быть любой из наших существующих служб Spring, содержащей метод, обработка которого в веб-запросе может занять слишком много времени. Это также может быть метод, который вызывает некоторые другие внешние службы, которым мы хотим добавить устойчивость, поскольку JobRunr повторит попытку метода в случае возникновения исключения.
5.2. Создание заданий типа «выстрелил-забыл»
Теперь, когда у нас есть зависимости, мы можем создавать задания типа «запустил и забыл», используя метод постановки
в очередь :
jobScheduler.enqueue(() -> sampleJobService.executeSampleJob());
Задания могут иметь параметры, как и любая другая лямбда:
jobScheduler.enqueue(() -> sampleJobService.executeSampleJob("some string"));
Эта строка гарантирует, что лямбда-выражение, включая тип, метод и аргументы, будет сериализовано в виде JSON в постоянное хранилище (СУБД, такая как Oracle, Postgres, MySql и MariaDB, или база данных NoSQL).
Выделенный рабочий пул потоков, запущенных во всех различных BackgroundJobServer
, затем выполнит эти поставленные в очередь фоновые задания как можно скорее в порядке «первым поступил — первым обслужен». JobRunr гарантирует выполнение вашей работы одним работником посредством оптимистической блокировки.
5.3. Планирование работы в будущем
Мы также можем планировать задания в будущем, используя метод schedule
:
jobScheduler.schedule(LocalDateTime.now().plusHours(5), () -> sampleJobService.executeSampleJob());
5.4. Повторное планирование заданий
Если мы хотим иметь повторяющиеся задания, нам нужно использовать метод scheduleRecurrently
:
jobScheduler.scheduleRecurrently(Cron.hourly(), () -> sampleJobService.executeSampleJob());
5.5. Аннотирование с помощью аннотации @Job
Чтобы контролировать все аспекты задания, мы можем аннотировать наш сервисный метод аннотацией @Job
. Это позволяет установить отображаемое имя на панели управления и настроить количество повторных попыток в случае сбоя задания.
@Job(name = "The sample job with variable %0", retries = 2)
public void executeSampleJob(String variable) {
...
}
Мы даже можем использовать переменные, которые передаются нашему заданию в отображаемом имени с помощью синтаксиса String.format()
.
Если у нас есть очень специфические варианты использования, когда мы хотели бы повторить определенное задание только при определенном исключении, мы можем написать свой собственный ElectStateFilter
, где у нас есть доступ к заданию
и полный контроль над тем, как действовать.
6. Панель управления
JobRunr поставляется со встроенной панелью инструментов, которая позволяет нам отслеживать нашу работу. Мы можем найти его по адресу http://localhost:8000 и проверить все задания, включая все повторяющиеся задания, и оценить, сколько времени потребуется, чтобы обработать все поставленные в очередь задания:
Могут случиться плохие вещи, например, срок действия SSL-сертификата истек, или диск переполнен. JobRunr по умолчанию перепланирует фоновое задание с экспоненциальной политикой отсрочки. Если фоновое задание продолжает сбой десять раз, только тогда оно перейдет в состояние « Ошибка
» . Затем вы можете решить повторно поставить невыполненное задание в очередь, когда основная причина будет устранена.
Все это отображается на панели инструментов, включая каждую повторную попытку с точным сообщением об ошибке и полной трассировкой стека, объясняющей, почему задание не удалось:
7. Заключение
В этой статье мы создали наш первый базовый планировщик, используя JobRunr с помощью jobrunr-spring-boot-starter
. Ключевым выводом из этого руководства является то, что мы смогли создать задание с помощью всего одной строки кода и без какой-либо конфигурации на основе XML или необходимости реализации интерфейса.
Полный исходный код примера доступен на GitHub .