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