Guía de ShedLock con resorte

1. Información general

Spring proporciona una API fácil de implementar para programar trabajos. Funciona muy bien hasta que implementamos varias instancias de nuestra aplicación. Spring, de forma predeterminada, no puede manejar la sincronización del programador en varias instancias; en su lugar, ejecuta los trabajos simultáneamente en cada nodo.

En este breve tutorial, veremos ShedLock, una biblioteca de Java que se asegura de que nuestras tareas programadas se ejecuten solo una vez al mismo tiempo y sea una alternativa a Quartz.

2. Dependencias de Maven

Para usar ShedLock con Spring, necesitamos agregarla dependencia shedlock-spring :

 net.javacrumbs.shedlock shedlock-spring 2.2.0 

3. Configuración

Tenga en cuenta que ShedLock solo funciona en entornos con una base de datos compartida al declarar un LockProvider adecuado . Crea una tabla o documento en la base de datos donde almacena la información sobre los bloqueos actuales.

Actualmente, ShedLock es compatible con Mongo, Redis, Hazelcast, ZooKeeper y cualquier cosa con un controlador JDBC.

Para este ejemplo, usaremos una base de datos H2 en memoria. Para que funcione, debemos proporcionar la base de datos H2 y la dependencia JDBC de ShedLock:

 net.javacrumbs.shedlock shedlock-provider-jdbc-template 2.1.0   com.h2database h2 1.4.200 

A continuación, necesitamos crear una tabla de base de datos para que ShedLock mantenga información sobre los bloqueos del programador:

CREATE TABLE shedlock ( name VARCHAR(64), lock_until TIMESTAMP(3) NULL, locked_at TIMESTAMP(3) NULL, locked_by VARCHAR(255), PRIMARY KEY (name) )

Debemos declarar la fuente de datos en el archivo de propiedades de nuestra aplicación Spring Boot para que el bean DataSource pueda conectarse automáticamente . En este ejemplo, usamos application.yml para definir la fuente de datos de la base de datos H2:

spring: datasource: driverClassName: org.h2.Driver url: jdbc:h2:mem:shedlock_DB;INIT=CREATE SCHEMA IF NOT EXISTS shedlock;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE username: sa password: 

Configuremos LockProvider con la configuración de la fuente de datos anterior. Spring puede hacerlo bastante sencillo:

@Configuration public class SchedulerConfiguration { @Bean public LockProvider lockProvider(DataSource dataSource) { return new JdbcTemplateLockProvider(dataSource); } }

Otro requisito de configuración que tenemos que proporcionar son las anotaciones @EnableScheduling y @EnableSchedulerLock en nuestra clase de configuración Spring:

@SpringBootApplication @EnableScheduling @EnableSchedulerLock(defaultLockAtMostFor = "PT30S") public class Application { public static void main(String[] args) { SpringApplication.run(SpringApplication.class, args); } }

El parámetro defaultLockAtMostFor especifica la cantidad predeterminada de tiempo que el bloqueo debe mantenerse en caso de que el nodo en ejecución muera. Utiliza el formato de duración ISO8601.

En la siguiente sección, veremos cómo anular este valor predeterminado.

4. Creación de tareas

Para crear una tarea programada manejada por ShedLock, simplemente colocamos las anotaciones @Scheduled y @SchedulerLock en un método:

@Component class BaeldungTaskScheduler { @Scheduled(cron = "0 0/15 * * * ?") @SchedulerLock(name = "TaskScheduler_scheduledTask", lockAtLeastForString = "PT5M", lockAtMostForString = "PT14M") public void scheduledTask() { // ... } }

Primero, veamos @Scheduled . Es compatible con el formato cron , con esta expresión que significa "cada 15 minutos".

A continuación, echando un vistazo a @SchedulerLock, el parámetro de nombre tiene que ser único, y ClassName_methodName suele ser suficiente para lograrlo. No queremos que se ejecute más de una ejecución de este método al mismo tiempo, y ShedLock usa el nombre único para lograrlo.

También agregamos un par de parámetros opcionales.

Primero, agregamos lockAtLeastForString para que podamos poner cierta distancia entre las invocaciones de métodos. El uso de “PT5M” significa que este método mantendrá la cerradura durante 5 minutos, como mínimo. En otras palabras, eso significa que ShedLock no puede ejecutar este método con más frecuencia que cada cinco minutos.

A continuación, agregamos lockAtMostForString para especificar cuánto tiempo debe mantenerse el bloqueo en caso de que el nodo en ejecución muera. El uso de “PT14M” significa que se bloqueará durante no más de 14 minutos.

En situaciones normales, ShedLock libera el bloqueo directamente después de que finaliza la tarea. Ahora, no tuvimos que hacer eso porque hay un valor predeterminado proporcionado en @EnableSchedulerLock , pero hemos elegido anularlo aquí.

5. Conclusión

En este artículo, hemos aprendido cómo crear y sincronizar tareas programadas con ShedLock.

Como siempre, todo el código fuente está disponible en GitHub.