为了解耦,我们往往会采用定时任务去做一些补偿或者耗时的操作。传统项目中定时任务会耦合在业务项目中,要知道定时任务底层依赖于死循环,大量的定时任务会导致业务系统卡死奔溃。所以有必要将定时任务和业务项目剥离出来,各司其职。浏览对比知名组件,xxl-job口碑好评如潮,所以记录下学习xxl-job的过程。
(ps:尊重原创,附上xxl地址:https://www.xuxueli.com/xxl-job/)
一、工作机制
xxl-job类似于微服务的注册中心。它提供两个角色:任务调度中心和执行器。
任务调度中心类似于注册中心,统一管理执行器的执行。
执行器也就是我们具体的应用在启动时自动或手动注册到任务调度中心的一种表现。
通俗易懂一点:任务调度中心类似于一个Map,存放多个键值对。执行器为key,value就是执行器对应的集群列表地址。
当我们需要调度任务时,获取集群列表地址通过指定的策略得到服务器地址发送请求,再通过反射执行定时任务即可。
二、搭建过程
1、任务调度中心
下载源码后解压
a、初始化数据库
执行 /xxl-job/doc/db/tables_xxl_job.sql
注意:调度中心支持集群部署,集群情况下各节点务必连接同一个mysql实例
mysql主从模式下必须连接主数据库
b、idea导入并编译源码
目录结构如下:
xxl-job-admin:调度中心
xxl-job-core:公共依赖
xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器) :
xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式; :
xxl-job-executor-sample-frameless:无框架版本;
c、配置部署调度中心
配置/xxl-job/xxl-job-admin/src/main/resources/application.properties文件
### 调度中心JDBC链接
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoRecOnnect=true&serverTimezOne=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
### 报警邮箱 根据自己邮箱类型设置
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
### 调度中心通讯TOKEN [选填]:非空时启用;如果开启,定时任务接口的项目也需要填写相同的token
xxl.job.accessToken=
### 调度中心国际化配置 [必填]: 默认为 "zh_CN"/中文简体, 可选范围为 "zh_CN"/中文简体, "zh_TC"/中文繁体 and "en"/英文;
xxl.job.i18n=zh_CN
## 调度线程池最大线程配置【必填】
xxl.job.triggerpool.fast.max=200
xxl.job.triggerpool.slow.max=100
### 调度中心日志表数据保存天数 [必填]:过期日志自动清理;限制大于等于7时生效,否则, 如-1,关闭自动清理功能;
xxl.job.logretentiOndays=30
d、编译启动项目
调度中心访问地址:http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址)
2、执行器
以Springboot项目为例
a、maven依赖
<dependency>
<groupId>com.xuxueligroupId>
<artifactId>xxl-job-coreartifactId>
<version>${最新稳定版本}version>
dependency>
b、application.yml配置
xxl:
job:
enabled: true
admin:
addresses: http://localhost:8080/xxl-job-admin
executor:
appname: myExecutor
ip: 127.0.0.1
port: 9999
logpath: /日志路径
logretentiondays: -1
accessToken: 调度中心d额token
c、配置类
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
d、定时任务接口
@Service
@Slf4j
@JobHandler(value = "myExecutor")
public class MyExecutor extends IJobHandler {
@Override
public ReturnT execute(String param) {
// 执行定时业务
return SUCCESS;
}
}
三、分片原理
当执行器集群后,如何保证定时任务幂等性原则呢?很简单,采用分片方式进行。任务调度中心会根据服务器的地址传递不同的分片值,执行器的定时任务可以根据分片值去分配不同区间的数据进行业务处理。
由此可以实现动态的扩容和锁容,当新的执行器服务器启动后,会自动注册至调度中心,调度中心根据集群地址的变化,进而调整分片值。