Lavori in background in primavera con JobRunr

1. Panoramica

In questo tutorial, esamineremo la pianificazione e l'elaborazione dei processi in background distribuiti in Java utilizzando JobRunr e lo integreremo con Spring.

2. Informazioni su JobRunr

JobRunr è una libreria che possiamo incorporare nella nostra applicazione e che ci permette di programmare processi in background utilizzando un lambda Java 8. Possiamo utilizzare qualsiasi metodo esistente dei nostri servizi Spring per creare un lavoro senza la necessità di implementare un'interfaccia. Un processo può essere un processo breve o di lunga durata e verrà automaticamente scaricato su un thread in background in modo che la richiesta Web corrente non venga bloccata.

Per fare il suo lavoro, JobRunr analizza il lambda Java 8. Lo serializza come JSON e lo archivia in un database relazionale o in un archivio dati NoSQL.

3. Caratteristiche di JobRunr

Se vediamo che stiamo producendo troppi processi in background e il nostro server non è in grado di far fronte al carico, possiamo facilmente scalare orizzontalmente semplicemente aggiungendo istanze extra della nostra applicazione. JobRunr condividerà il carico automaticamente e distribuirà tutti i lavori sulle diverse istanze della nostra applicazione.

Contiene anche una funzione di ripetizione automatica dei tentativi con un criterio di backoff esponenziale per i lavori non riusciti. C'è anche una dashboard integrata che ci consente di monitorare tutti i lavori. JobRunr è a manutenzione automatica: i lavori riusciti verranno eliminati automaticamente dopo un periodo di tempo configurabile, quindi non è necessario eseguire la pulizia manuale della memoria.

4. Configurazione

Per semplicità, utilizzeremo un archivio dati in memoria per archiviare tutte le informazioni relative al lavoro.

4.1. Configurazione Maven

Passiamo direttamente al codice Java. Ma prima, dobbiamo avere la seguente dipendenza Maven dichiarata nel nostro file pom.xml :

 org.jobrunr jobrunr-spring-boot-starter 1.1.0 

4.2. Spring Integration

Prima di passare direttamente a come creare lavori in background, dobbiamo inizializzare JobRunr. Dato che stiamo usando la dipendenza jobrunr-spring-boot-starter , questo è facile. Abbiamo solo bisogno di aggiungere alcune proprietà a application.properties :

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

La prima proprietà dice a JobRunr che vogliamo avviare un'istanza di un BackgroundJobServer responsabile dell'elaborazione dei lavori. La seconda proprietà indica a JobRunr di avviare il dashboard incorporato.

Per impostazione predefinita, jobrunr-spring-boot-starter proverà a utilizzare il DataSource esistente nel caso di un database relazionale per memorizzare tutte le informazioni relative al lavoro.

Tuttavia, poiché utilizzeremo un archivio dati in memoria, dobbiamo fornire un bean StorageProvider :

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

5. Utilizzo

Ora, scopriamo come creare e programmare processi in background in Spring utilizzando JobRunr.

5.1. Iniettare dipendenze

Quando vogliamo creare lavori, dovremo iniettare JobScheduler e il nostro servizio Spring esistente contenente il metodo per il quale vogliamo creare lavori, in questo caso, il SampleJobService :

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

La classe JobScheduler di JobRunr ci consente di accodare o pianificare nuovi processi in background.

Il SampleJobService potrebbe essere uno qualsiasi dei nostri servizi di primavera esistenti che contengono un metodo che potrebbe richiedere troppo tempo per gestire in una richiesta web. Può anche essere un metodo che chiama alcuni altri servizi esterni in cui si desidera aggiungere resilienza poiché JobRunr ritenterà il metodo se si verifica un'eccezione.

5.2. Creazione di lavori da dimenticare

Ora che abbiamo le nostre dipendenze, possiamo creare lavori spara e dimentica utilizzando il metodo di accodamento :

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

I lavori possono avere parametri, proprio come qualsiasi altro lambda:

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

Questa riga assicura che il lambda, inclusi tipo, metodo e argomenti, sia serializzato come JSON nello storage persistente (un RDBMS come Oracle, Postgres, MySql e MariaDB o un database NoSQL).

Un pool di thread di lavoro dedicato in esecuzione in tutti i diversi BackgroundJobServer eseguirà quindi questi processi in background in coda il prima possibile, in modo first-in-first-out. JobRunr garantisce l'esecuzione del tuo lavoro da parte di un singolo lavoratore tramite il lock ottimistico.

5.3. Pianificazione dei lavori in futuro

Possiamo anche pianificare i lavori in futuro utilizzando il metodo di pianificazione :

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

5.4. Pianificazione dei lavori in modo ricorrente

Se vogliamo avere lavori ricorrenti, dobbiamo utilizzare il metodo scheduleRecurrently :

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

5.5. Annotazione con @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 questo articolo, abbiamo creato il nostro primo scheduler di base utilizzando JobRunr con jobrunr-spring-boot-starter . Il punto chiave di questo tutorial è che siamo stati in grado di creare un lavoro con una sola riga di codice e senza alcuna configurazione basata su XML o la necessità di implementare un'interfaccia.

Il codice sorgente completo per l'esempio è disponibile su GitHub.