700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解

SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解

时间:2020-07-17 14:14:25

相关推荐

SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解

目录

前言

SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解

一、关于ShedLock

二、ShedLock的三个核心组件

三、ShedLock使用三步走

四、SpringBoot集成ShedLock(基于JDBC来提供锁)

五、Spring 集成 ShedLock的两种模式

前言

前段时间,根据项目要求,需要实现微服务的高可用,即,将某个服务部署多个实例,但是其中涉及到了很多定时任务调度的问题(。。。其他废话不多说),思来想去,暂定使用了 ShedLock 来实现分布式定时任务锁,本篇主要介绍了SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解。

SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解

一、关于ShedLock

ShedLock采用非侵入式编程的思想,通过注解的方式来实现相应的功能。ShedLock是一个在分布式环境中使用的定时任务框架,用于解决在分布式环境中的多个实例的相同定时任务在同一时间点重复执行的问题,解决思路是通过对公用的数据库中的某个表进行记录和加锁,使得同一时间点只有第一个执行定时任务并成功在数据库表中写入相应记录的节点能够成功执行而其他节点直接跳过该任务。当然不只是数据库,目前已经实现的支持数据存储类型除了经典的关系型数据库,还包括JDBC、Redis、MongoDB、CosmosDB、DynamoDB、以及分布式协调服务Zookeeper、还有ElasticSearch等等,是非常的丰富的。

二、ShedLock的三个核心组件

Core- 锁机制

Integration- 通过Spring AOP、Micronaut AOP或者手写代码进行与应用程序的集成

Lock provider- 使用关系型数据库(RDBMS),非关系型数据库:Mongo、Redis等外部进程来提供锁

三、ShedLock使用三步走

1)、启用并配置Scheduled的锁

2)、在Scheduled任务上面添加注解

3)、配置锁的提供者(JDBC、Redis、Mongo等)

四、SpringBoot集成ShedLock(基于JDBC来提供锁)

1)、在pom.xml中新增引入Spring整合ShedLock依赖包

<dependency><groupId>net.javacrumbs.shedlock</groupId><artifactId>shedlock-spring</artifactId><version>3.0.1</version></dependency><dependency><groupId>net.javacrumbs.shedlock</groupId><artifactId>shedlock-provider-jdbc-template</artifactId><version>3.0.1</version></dependency>

2)、配置LockProvider,这里使用的JDBC,所以需要配置JDBC的LockProvider,在每个实例对应的数据库中新建锁表-shedlock表(请注意名称须是主键)建表语句如下:

CREATE TABLE shedlock(name VARCHAR(64), lock_until TIMESTAMP(3) NULL, locked_at TIMESTAMP(3) NULL, locked_by VARCHAR(255), PRIMARY KEY (name));COMMENT ON COLUMN "shedlock"."name" IS '锁名称(name必须是主键)';COMMENT ON COLUMN "shedlock"."lock_until" IS '释放锁时间';COMMENT ON COLUMN "shedlock"."locked_at" IS '获取锁时间';COMMENT ON COLUMN "shedlock"."locked_by" IS '锁提供者';

*注意:基于关系型数据库(RDBMS)的形式的外部存储必须创建表结构,而非关系型,例如:Redis等非关系型数据库形式的外部存储,template会根据注解 @SchedulerLock 声明的锁名称自动创建对应的键值对,以此来提供锁的实现。

3)、配置LockProvider,关于LockProvider有几种配置实现,这儿以JDBC为实现的,

package com.mon.config;import net.javacrumbs.shedlock.core.LockProvider;import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;/*** * @author HuaZai* @contact who.seek.me@java98k.vip*<ul>* @description 配置 LockProvider* </ul>* @className ShedlockConfig* @package com.mon.config* @createdTime 03月20日** @version V1.0.0*/@Configurationpublic class ShedlockConfig{@Beanpublic LockProvider lockProvider(DataSource dataSource){return new JdbcTemplateLockProvider(dataSource);}}

当然还有更细粒度的配置,通过 Configuration 对象来实现,可以自己去尝试一下,内容如下:

new JdbcTemplateLockProvider(builder().withTableName("shdlck").withColumnNames(new ColumnNames("n", "lck_untl", "lckd_at", "lckd_by")).withJdbcTemplate(new JdbcTemplate(getDatasource())).withLockedByValue("my-value").build())

*注意:在ShedLock使用的过程中,千万不要从数据库表中手动删除锁行或文档。ShedLock有一个现有锁的内存缓存,因此在应用程序重新启动之前不会自动重新创建该行。如果需要,您可以编辑行或文档,这样做的风险是只持有多个锁。在1.0.0可以通过调用LockProvider上的clearCache()方法来清除缓存。

4)、在项目的启动类中新增 “@EnableSchedulerLock ” 注解,开启ShedLock

package com.huazai.aiyou.controller;import net.javacrumbs.shedlock.spring.annotation.EnableSchedulerLock;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.cache.annotation.EnableCaching;import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.flix.eureka.EnableEurekaClient;import org.flix.hystrix.EnableHystrix;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.scheduling.annotation.EnableScheduling;/*** * @author HuaZai* @contact who.seek.me@java98k.vip*<ul>* @description 门户网站Web端启动类* </ul>* @className AiyouApplication* @package com.huazai.aiyou* @createdTime 03月20日** @version V1.0.0*/@EnableHystrix@EnableCaching@EnableDiscoveryClient@EnableFeignClients@EnableEurekaClient@EnableCircuitBreaker@EnableAutoConfiguration@EnableScheduling@EnableSchedulerLock(defaultLockAtMostFor = "PT20M", defaultLockAtLeastFor = "PT20M")public class AiyouApplication{public static void main(String[] args){SpringApplication.run(AiyouApplication.class, args);}}

5)、在需要加锁的Scheduled任务上添加注解 “@SchedulerLock ”

package com.huazai.aiyou.controller.task.schedu;import com.alibaba.fastjson.JSONObject;import lombok.extern.slf4j.Slf4j;import net.javacrumbs.shedlock.core.SchedulerLock;import mons.collections4.CollectionUtils;import mons.collections4.MapUtils;import mons.lang3.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import java.util.ArrayList;import java.util.List;import java.util.Map;/*** * @author HuaZai* @contact who.seek.me@java98k.vip*<ul>* @description TODO* </ul>* @className TaskSchedulerController* @package com.huazai.aiyou* @createdTime 03月20日** @version V1.0.0*/@RestController@Slf4jpublic class TaskSchedulerController extends BaseController{// TODO/*** * @author HuaZai* @contact who.seek.me@java98k.vip* @title sendItemInfoMessage* <ul>* @description TODO* </ul>* @createdTime 03月20日* @throws GlobalException* @return void** @version : V1.0.0*/@Scheduled(cron = "0 0 0 * * ?")@SchedulerLock(name = "sendItemInfoMessage")public void sendItemInfoMessage() throws GlobalException{try{// TODO} catch (Exception e){throw new GlobalException(ExceptionCode.global.ITEM_FAIL, ParamContext.NONE_ITEM_INFO);}}}

参数说明:

@SchedulerLock 作用:只有某个方法上添加了该注解的方法才会被锁定,该库将忽略所有其他计划任务。且必须为锁指定名称,这样才能在同一时间只能有一个具有相同名称的任务执行,以达到预期的锁的目的。

@EnableSchedulerLock 作用:开启ShedLock的支持

*注意:通过设置lockAtMostFor,我们可以确保即使该节点死亡,锁也会被正常释放;通过设置lockAtLeastFor,我们可以确保它在指定的时间内不会执行超过一次。请注意,对于执行任务的节点死亡的情况,lockAtMostFor只是能确保节点执行的一个安全范围,所以在设置这个时间时,这个时间需要远远大于最大评估任务的执行时间。如果任务执行花费的时间比设置的lockAtMostFor更长,那么它可能会再次执行,以至于出现同一个任务重复执行的情况,结果将是不可预测的(导致更多的进程持有锁)。

五、Spring 集成 ShedLock的两种模式

ShedLock支持两种Spring集成模式。一个是使用关于调度方法的AOP代理(PROXY_METHOD),另一个是代理任务调度器(PROXY_SCHEDULER),如下图:

关于ShedLock的集成模式,一般情况下都是使用的默认值,了解一下就可以,这儿就不再写了,如果有兴趣的小伙伴可以去官网查看。

参考文献:

ShedLock GitHub 相关文档:/lukas-krecan/ShedLock

好了,关于SpringBoot2.x整合轻量级分布式定时任务ShedLock3.x的使用详解 就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。

歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。