Hintergrundjobs im Frühjahr bei JobRunr

1. Übersicht

In diesem Tutorial werden wir uns mit der verteilten Planung und Verarbeitung von Hintergrundjobs in Java mithilfe von JobRunr befassen und diese in Spring integrieren.

2. Über JobRunr

JobRunr ist eine Bibliothek, die wir in unsere Anwendung einbetten können und die es uns ermöglicht, Hintergrundjobs mit einem Java 8-Lambda zu planen. Wir können jede vorhandene Methode unserer Spring-Services verwenden, um einen Job zu erstellen, ohne eine Schnittstelle implementieren zu müssen. Ein Job kann ein kurzer oder langwieriger Prozess sein und wird automatisch in einen Hintergrundthread verlagert, damit die aktuelle Webanforderung nicht blockiert wird.

JobRunr analysiert dazu das Java 8-Lambda. Es serialisiert es als JSON und speichert es entweder in einer relationalen Datenbank oder in einem NoSQL-Datenspeicher.

3. JobRunr-Funktionen

Wenn wir feststellen, dass wir zu viele Hintergrundjobs produzieren und unser Server die Last nicht bewältigen kann, können wir einfach horizontal skalieren, indem wir einfach zusätzliche Instanzen unserer Anwendung hinzufügen. JobRunr teilt die Last automatisch und verteilt alle Jobs auf die verschiedenen Instanzen unserer Anwendung.

Es enthält auch eine automatische Wiederholungsfunktion mit einer exponentiellen Backoff-Richtlinie für fehlgeschlagene Jobs. Es gibt auch ein integriertes Dashboard , mit dem wir alle Jobs überwachen können. JobRunr ist selbstverwaltend - erfolgreiche Jobs werden nach einer konfigurierbaren Zeit automatisch gelöscht, sodass keine manuelle Speicherbereinigung erforderlich ist.

4. Setup

Der Einfachheit halber verwenden wir einen speicherinternen Datenspeicher, um alle auftragsbezogenen Informationen zu speichern.

4.1. Maven-Konfiguration

Lassen Sie uns direkt zum Java-Code springen. Zuvor muss jedoch die folgende Maven-Abhängigkeit in unserer Datei pom.xml deklariert sein :

 org.jobrunr jobrunr-spring-boot-starter 1.1.0 

4.2. Frühlingsintegration

Bevor wir direkt mit dem Erstellen von Hintergrundjobs beginnen, müssen wir JobRunr initialisieren. Da wir die Jobrunr-Spring-Boot-Starter- Abhängigkeit verwenden, ist dies einfach. Wir müssen der application.properties nur einige Eigenschaften hinzufügen :

org.jobrunr.background-job-server.enabled=true org.jobrunr.dashboard.enabled=true

Die erste Eigenschaft teilt JobRunr mit, dass eine Instanz eines BackgroundJobServers gestartet werden soll, der für die Verarbeitung von Jobs verantwortlich ist. Die zweite Eigenschaft weist JobRunr an, das eingebettete Dashboard zu starten.

Standardmäßig versucht der Jobrunr-Spring-Boot-Starter , Ihre vorhandene DataSource im Falle einer relationalen Datenbank zum Speichern aller jobbezogenen Informationen zu verwenden.

Da wir jedoch einen speicherinternen Datenspeicher verwenden, müssen wir eine StorageProvider- Bean bereitstellen :

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

5. Verwendung

Lassen Sie uns nun herausfinden, wie Sie mit JobRunr Hintergrundjobs im Frühjahr erstellen und planen.

5.1. Abhängigkeiten injizieren

Wenn wir Jobs erstellen möchten, müssen wir den JobScheduler und unseren vorhandenen Spring-Service einfügen , der die Methode enthält, für die wir Jobs erstellen möchten, in diesem Fall den SampleJobService :

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

Mit der JobScheduler- Klasse von JobRunr können wir neue Hintergrundjobs in die Warteschlange stellen oder planen.

Der SampleJobService kann einer unserer vorhandenen Spring-Services sein, der eine Methode enthält, deren Verarbeitung in einer Webanforderung möglicherweise zu lange dauert . Es kann sich auch um eine Methode handeln, die einige andere externe Dienste aufruft, bei denen die Ausfallsicherheit erhöht werden soll, da JobRunr die Methode wiederholt, wenn eine Ausnahme auftritt.

5.2. Erstellen von Fire-and-Forget-Jobs

Nachdem wir nun unsere Abhängigkeiten haben, können wir mithilfe der Enqueue- Methode Fire-and-Forget-Jobs erstellen :

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

Jobs können wie jedes andere Lambda Parameter haben:

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

Diese Zeile stellt sicher, dass das Lambda - einschließlich Typ, Methode und Argumente - als JSON für dauerhaften Speicher serialisiert wird (ein RDBMS wie Oracle, Postgres, MySql und MariaDB oder eine NoSQL-Datenbank).

Ein dedizierter Worker-Pool von Threads, die auf allen verschiedenen BackgroundJobServern ausgeführt werden, führt diese Hintergrundjobs in der Warteschlange so schnell wie möglich in einer First-In-First-Out-Weise aus. JobRunr garantiert die Ausführung Ihres Jobs durch einen einzelnen Mitarbeiter durch optimistisches Sperren.

5.3. Jobs in der Zukunft planen

Wir können Jobs auch in Zukunft mithilfe der Planungsmethode planen :

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

5.4. Jobs neu planen

Wenn wir wiederkehrende Jobs haben möchten, müssen wir die Methode schedRecurrently verwenden:

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

5.5. Kommentieren mit der @ Job- Annotation

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

In diesem Artikel haben wir unseren ersten Basisplaner mit JobRunr mit dem Jobrunr-Spring-Boot-Starter erstellt . Die wichtigste Erkenntnis aus diesem Tutorial ist, dass wir einen Job mit nur einer Codezeile erstellen konnten, ohne dass eine XML-basierte Konfiguration erforderlich war oder eine Schnittstelle implementiert werden musste.

Der vollständige Quellcode für das Beispiel ist auf GitHub verfügbar.