文章目录
前言(之前的项目回顾)
座右铭:明镜止水 举重若轻
在我之前项目中经历中,有很多场景是需要定制任务来完成的。比如之前的社区批量下发门禁卡,异步下发完毕后有些门禁机会出现长时间无回应的问题。但是在我们数据库中卡号已经全变成了发卡中。这时候我们就需要一个定时任务批量的将长时间处在发卡中的门禁卡批量改为发卡失败。
滔滔又来讲解了
一、初级的定时任务?
这里只要是做过开发的同学们,就应该猜到我要讲的是什么。没错!就是Spring自带的@Scheduled注解。使用的方法也非常简单就是创建一个类,在类上添加@Component注解交给Spring管理,随后在方法上添加@Scheduled 添加cron表达式,到了指定时间就会自动执行,简单快捷就可以实现简单的定时任务。
但是随着系统越来越复杂,逐渐出现了多节点分布式的框架架构。举个例子,加入一个data服务有3个节点,三个节点都是同样的代码。都设定了下午两点启动定时任务。如果不加同步锁的情况下,就会出现一个定时任务执行三次的问题。所以针对这种情况 出现了分布式锁 我之前用的就是基于redis的 Redision分布式锁。
redision分布式锁的基本原理就是他会在redis中存入一个key键值,由于redis是单线程的。三个节点会有一个抢先到当当前缓存的线程,并将键值放入缓存中。后续其他的服务节点通过唯一的key在缓存中查找,如果在缓存中找到,则说明已经有节点已经正在执行定时任务了,从而退出本次任务 等待下次继续执行。
二、XXL-job的出现
在上面我们讲解了基础的定时任务以及分布式锁,虽然能满足项目里最基本的需要,但是会逐渐暴露问题,随着项目的需求修改,定时任务会越来越多,每个定时方法上都要手动添加注解以及填写cron表达式 一个两个还好,等到后面越来越多 出现了维护困难的问题,无法做到统一管理。此时出现了XXL—job(感谢亲哥教导)。
https://www.xuxueli.com/xxl-job/ 官网地址
xxjob对定时任务进行了统一管理,要我自己说有几个优点。
1.低嵌入式
我只需要在我的项目里引入xxjob的maven包,就可以使用xxljob(后面教怎么使用,给我接着往下看)
2.方便管理
xxljob有一个简单易懂的客户端 直接通过ip以及端口就可以访问进去,一眼就可以看到有多少定时任务 以及成功失败的次数,也可以自己定义icon表达式 和代码分离。不需要在代码里写icon表达式,非常的舒服。
3.最后一个 省去分布式锁
同一个定时任务只会自动的选择一个执行器去执行。不需要在原来的代码里手动写入redision分布式锁。以防同一个定时任务多次执行。
三、具体的安装教程
我就喜欢用大白话讲技术,不玩虚的。
xxljob就两个部分一个是客户端,一个是执行器(就是你的Spring项目)
1.进入官网下载项目
2.执行sql以及将项目放入idea中
这是xxljob需要的sql文件 在mysql中执行
把-admin项目导入idea 修改你的数据库配置,开始打jar包(记住你的端口号)
3.在linux上启动你的jar包
4.直接访问你的xxl-job服务(默认的账号密码admin,123456)
5.配置你的Spring项目(执行器部分)
引入xxljob的maven包
6.新增关于xxl-job的config文件
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.appname}")
private String appname;
@Value("${xxl.job.executor.address}")
private String address;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
/**
* 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
*
* 1、引入依赖:
* <dependency>
* <groupId>org.springframework.cloud</groupId>
* <artifactId>spring-cloud-commons</artifactId>
* <version>${version}</version>
* </dependency>
*
* 2、配置文件,或者容器启动变量
* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
*
* 3、获取IP
* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
*/
}
7.在对应的定时方法上新增注解(我这里是用的方法bean的方式)
8.在xxjob客户端上新增任务
9.手动执行以及定时执行
10.查看调用是否成功日志
四、总结
本次关于xxl-job的讲解就到这里了,其实支持很多其他的方式使用,我这里只是用了最简单的方法bean的方式进行启动定时任务,更多方法可以去xxljob的官网去查看。