跳至主要内容

在Spring Boot的schedule中使用shedlock

java-reflection-method-handle.md

简介

Spring Boot中使用内置的schedule时,在多个实例部署的情况下,如果只想让其中一个实例执行,可以自己用redis、zookeeper等实现,也可以直接用第三方实现。下面介绍其中一种实现:shedlock。

Shedlock

shedlock的集成比较简单,首先在start.spring.io生成Spring Boot的demo包,再引入shedlock相关的依赖:


<dependency>

<groupId>net.javacrumbs.shedlock</groupId>

<artifactId>shedlock-provider-redis-spring</artifactId>

<version>4.41.0</version>

</dependency>

<dependency>

<groupId>net.javacrumbs.shedlock</groupId>

<artifactId>shedlock-spring</artifactId>

<version>4.41.0</version>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

由于是使用redis来实现锁,所以需要增加spring data redis相关依赖。

然后在启动类加上开启定时任务的注解:


@EnableScheduling

@SpringBootApplication

public  class  SchedulerLockApplication {

  

public  static  void  main(String[] args) {

SpringApplication.run(SchedulerLockApplication.class, args);

}

}

再加上对应的注解配置类:


@Configuration

@EnableSchedulerLock(defaultLockAtMostFor = "5m")

public  class  SchedulerLockConfig {

  

@Bean

public  LockProvider  lockProvider(RedisConnectionFactory  redisConnectionFactory){

return  new  RedisLockProvider(redisConnectionFactory);

}

  

}

  • @EnableSchedulerLock 注解就是开启SchedulerLock,必须配置的参数defaultLockAtMostFor表示锁最长存在多久。避免比如实例挂掉的情况下,锁无法释放的情况

  • LockProvider有多种实现,如JDBC、redis、zookeeper等,这里选用的是redis

下面是执行任务的schedule相关类:


@Slf4j

@Component

public  class  ScheduleTask {

  

@Scheduled(cron = "0 0/1 * * * ?")

@SchedulerLock(name = "taskExecuteLock", lockAtLeastFor = "10s")

public  void  taskExecute() {

LockAssert.assertLocked();

log.info("task execute ...");

}

}

  • @SchedulerLock 注解的name表示锁的名字,lockAtLeastFor是即使任务执行结束,也让锁保留的一段时间的配置。目的是为了防止任务很快执行完,锁也很快释放掉,导致另外有些慢的实例认为还没有执行而导致的重复执行

  • LockAssert.assertLocked()的作用是为了保证该次执行获取到了锁。比如有些情况下,错误的配置导致注解没有生效,那么执行到了这段就会报错,方便确认锁确实已经生效

总结

可以看到有了shedlock的支持,可以轻松实现多个实例,只执行一次schedule任务。

参考资料

[1]示例工程:spring-boot-demos/scheduler-lock-demo fengdongyi/spring-boot-demos (github.com)

评论

此博客中的热门博文

国密SM2签名封装成PKCS7格式

在国内做金融行业,难免会有被强制使用国密算法的情况,而且一般还会指定必须使用硬件加密机之类的设备,所以我也稍微的研究了一下国密算法,使用软算法签名并封装 PKCS7 格式(文档中的一个交互)。 以下是基于 Bouncy Castle 的示例,密钥对的生成可以参考 Bouncy Castle 中 test 包下 SM2 相关代码 public static String sign ( ) throws Exception { //加载公钥 byte [ ] plainText = "hello, world" . getBytes ( ) ; FileInputStream input = new FileInputStream ( "F:\\certificate\\public.cer" ) ; CertificateFactory certificateFactory = new CertificateFactory ( ) ; X509Certificate certificate = ( X509Certificate ) certificateFactory . engineGenerateCertificate ( input ) ; input . close ( ) ; //加载私钥,private为换成实际的私钥 PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec ( "private" . getBytes ( ) ) ; //SM2算法实际上为ECC算法,并指定了一些参数值,所以这里的参数是EC KeyFactory factory = KeyFactory . getInstance ( "EC" , "BC" ) ; PrivateKey privateKey = factory . generatePrivate ( spec ) ; //以下为签名并封装成PKCS7格式 byte [ ] signedMessag

Spring Boot Actuator 2 示例

Welcome file 简介 Spring Boot Actuator为应用程序提供了各种开箱即用的运维特性,可以与应用方便的交互和监控。 使用环境:Java 11 和 Spring Boot 2.4.3.RELEASE 集成Spring Boot Actuator 在Spring Boot中集成Spring Boot Actuator与集成其他的框架类似,在 pom.xml 里引入相关的starter就可以: < dependency > < groupId > org.springframework.boot </ groupId > < artifactId > spring-boot-starter-actuator </ artifactId > </ dependency > < dependency > < groupId > org.springframework.boot </ groupId > < artifactId > spring-boot-starter-web </ artifactId > </ dependency > 由于大部分的使用场景还是web,所以这里也用Spring MVC做示例。 配置好 pom.xml 后,默认actuator仅暴露一些基本功能,实际使用中,根据需求暴露对应功能。为了简便测试,这里在 application.yml 中配置暴露全部功能: management : endpoints : web : exposure : include : "*" endpoint : health : enabled : true show-details : always probes : enabled : true shutdown : enabled : true metr

NextCloud数据目录迁移

最近服务器的环境坏了,所以迁移了NextCloud的数据目录。不过在迁移过程中有点小问题。 环境: Ubuntu 18.04 Docker 19.03.7 1.NextCloud页面不正常,Docker日志显示XX目录permission denied 参考了 这里 的做法,不过是把  /var/www/html/   整个目录的权限都修改为  chown -R www-data:www-data ,之后就不再报权限问题了。 2.数据库配置修改 因为NextCloud是在初始化时填的数据库连接信息,所以直接迁移数据目录的情况下,会导致应用连不到新的数据库环境。此时可以找到数据目录下的  config/config.php 文件,直接修改数据库连接配置。