Фонові робочі місця навесні з JobRunr

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 :

 org.jobrunr jobrunr-spring-boot-starter 1.1.0 

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 спробує використати ваш існуючий DataSource у випадку реляційної бази даних для зберігання всієї інформації, пов’язаної із роботою.

Однак, оскільки ми будемо використовувати сховище даних у пам’яті, нам потрібно надати компонент StorageProvider :

@Bean public StorageProvider storageProvider(JobMapper jobMapper) { InMemoryStorageProvider storageProvider = new InMemoryStorageProvider(); storageProvider.setJobMapper(jobMapper); return storageProvider; }

5. Використання

Тепер давайте з’ясуємо, як створювати та планувати фонові завдання навесні за допомогою JobRunr.

5.1. Ін’єкційні залежності

Коли ми хочемо створити робочі місця, нам потрібно буде ввести JobScheduler і нашу існуючу службу Spring, що містить метод, для якого ми хочемо створити робочі місця, в даному випадку SampleJobService :

@Inject private JobScheduler jobScheduler; @Inject private SampleJobService sampleJobService;

Клас JobScheduler від JobRunr дозволяє нам розміщувати в черзі або планувати нові фонові завдання.

SampleJobService може бути будь-який з наших існуючих пружинні послуг , що містять метод , який може зайняти занадто багато часу , щоб впоратися з веб - запиту. Це також може бути метод, який викликає деякі інші зовнішні служби, де ми хочемо додати стійкість, оскільки JobRunr повторить спробу методу у разі виникнення винятку.

5.2. Створення пожежних і незабутніх робочих місць

Тепер, коли ми маємо свої залежності, ми можемо створювати робочі місця "забудь і забувай", використовуючи метод enqueue :

jobScheduler.enqueue(() -> sampleJobService.executeSampleJob());

Вакансії можуть мати параметри, як і будь-яка інша лямбда:

jobScheduler.enqueue(() -> sampleJobService.executeSampleJob("some string"));

Цей рядок гарантує, що лямбда - включаючи тип, метод та аргументи - серіалізується як JSON до постійного сховища (СУБД, такі як Oracle, Postgres, MySql та MariaDB або база даних NoSQL).

Виділений робочий пул потоків, що виконується у всіх різних BackgroundJobServer , потім виконуватиме ці фонові завдання в черзі якомога швидше, в порядку першого в першому. JobRunr гарантує виконання вашої роботи одним працівником за допомогою оптимістичного блокування.

5.3. Планування робочих місць у майбутньому

Ми також можемо запланувати роботу в майбутньому, використовуючи метод розкладу :

jobScheduler.schedule(() -> sampleJobService.executeSampleJob(), LocalDateTime.now().plusHours(5));

5.4. Планування робочих місць періодично

Якщо ми хочемо мати періодичні завдання, нам потрібно використовувати метод scheduleRecurrently :

jobScheduler.scheduleRecurrently(() -> sampleJobService.executeSampleJob(), Cron.hourly());

5.5. Анотація за допомогою анотації @Job

To control all aspects of a job, we can annotate our service method with the @Job annotation. This allows setting the display name in the dashboard and configuring the number of retries in case a job fails.

@Job(name = "The sample job with variable %0", retries = 2) public void executeSampleJob(String variable) { ... }

We can even use variables that are passed to our job in the display name by means of the String.format() syntax.

If we have very specific use cases where we would want to retry a specific job only on a certain exception, we can write our own ElectStateFilter where we have access to the Job and full control on how to proceed.

6. Dashboard

JobRunr comes with a built-in dashboard that allows us to monitor our jobs. We can find it at //localhost:8000 and inspect all the jobs, including all recurring jobs and an estimation of how long it will take until all the enqueued jobs are processed:

Bad things can happen, for example, an SSL certificate expired, or a disk is full. JobRunr, by default, will reschedule the background job with an exponential back-off policy. If the background job continues to fail ten times, only then will it go to the Failed state. You can then decide to re-queue the failed job when the root cause has been solved.

All of this is visible in the dashboard, including each retry with the exact error message and the complete stack trace of why a job failed:

7. Conclusion

У цій статті ми створили свій перший базовий планувальник за допомогою JobRunr із jobrunr-spring-boot-starter . Ключовим виводом цього підручника є те, що ми змогли створити роботу лише з одним рядком коду, без будь-якої конфігурації на основі XML або необхідності впровадження інтерфейсу.

Повний вихідний код для прикладу доступний на GitHub.