✔️1. 了解常用的分布式应用定时任务框架
✔️2. 掌握xxl-job定时任务框架搭建及使用
xxl-job
: 是大众点评员工徐雪里于2015年发布的分布式任务调度平台,是一个轻量级分布式任务调度框架,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。Quartz
:Java事实上的定时任务标准。但Quartz关注点在于定时任务而非数据,并无一套根据数据处理而定制化的流程。虽然Quartz可以基于数据库实现作业的高可用,但缺少分布式并行调度的功能TBSchedule
:阿里早期开源的分布式任务调度系统。代码略陈旧,使用timer而非线程池执行任务调度。众所周知,timer在处理异常状况时是有缺陷的。而且TBSchedule作业类型较为单一,只能是获取/处理数据一种模式。还有就是文档缺失比较严重elastic-job(E-Job)
:当当开发的弹性分布式任务调度系统,功能丰富强大,采用zookeeper实现分布式协调,实现任务高可用以及分片,目前是版本2.15,并且可以支持云开发Saturn
:是唯品会自主研发的分布式的定时任务的调度平台,基于当当的elastic-job 版本1开发,并且可以很好的部署到docker容器上。设计思想:
本文使用版本为2.3.0
3.1 主要修改配置:
### xxl-job, datasource
spring.datasource.url=jdbc:mysql://localhost: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.cj.jdbc.Driver
### xxl-job, email
spring.mail.host=smtp.qq.com
spring.mail.port=25
[email protected]
[email protected]
spring.mail.password=你的mail token
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 [选填]:非空时启用;
### xxl-job, access token
xxl.job.accessToken=ljwtoken
复制代码
3.2. 打包部署“调度中心”
3.3. 访问调度中心
该地址执行器配置文件xxl.job.admin.addresses将会使用到,作为回调地址
)可直接使用,也可以参考其并将现有项目改造成执行器
)4.1 maven依赖
com.xuxueli
xxl-job-core
${project.parent.version}
复制代码
4.2 修改配置文件:
### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### xxl-job, access token 自定义的token,要和admin模块配置的一致
xxl.job.accessToken=ljwtoken
### xxl-job executor appname 自定义名称,后台配置必须对应
xxl.job.executor.appname=xxl-job-executor-sample
### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
xxl.job.executor.address=
### xxl-job executor server-info
xxl.job.executor.ip=127.0.0.1
xxl.job.executor.port=9999
复制代码
4.3 执行器组件配置 要配置执行器组件,配置文件参考地址:/xxl-job/xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/core/config/XxlJobConfig.java
@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;
}
复制代码
4.4 部署执行器项目
GLUE模式(Java)原理:任务以源码方式维护在调度中心;该模式的任务实际上是一段继承自IJobHandler的Java类代码并 "groovy" 源码方式维护,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务(请确保Glue代码中的服务和类引用在“执行器”项目中存在),然后调用该对象的execute方法,执行任务逻辑。
GLUE模式(Java)就是在界面编写代码即可,不用在执行器项目中编写代码
5.1 新建任务
5.2 “GLUE模式(Java)” 任务开发
5.3 触发执行
5.4 查看日志:
请点击任务右侧 “调度日志” 按钮,可前往任务日志界面查看任务日志。
在任务日志界面中,可查看该任务的历史调度记录以及每一次调度的任务调度信息、执行参数和执行信息。运行中的任务点击右侧的“执行日志”按钮,可进入日志控制台查看实时执行日志。
6.1.1 优缺点
6.1.2 执行器项目中,开发Job类
注:版本v2.2.0 移除旧类注解@JobHandler,推荐使用基于方法注解@XxlJob的方式进行任务开发;(如需保留类注解JobHandler使用方式,可以参考旧版逻辑定制开发);
public class MyJobHandler extends IJobHandler {
@Override
public void execute() throws Exception {
XxlJobHelper.log("11==============MyJobHandler=================");
System.out.println("22==============MyJobHandler=================");
}
}
复制代码
注入myJobHandler:
@SpringBootApplication
public class XxlJobExecutorApplication {
public static void main(String[] args) {
SpringApplication.run(XxlJobExecutorApplication.class, args);
XxlJobExecutor.registJobHandler("myJobHandler", new MyJobHandler());
}
}
复制代码
6.1.3 调度中心,新建调度任务
6.2.1 优缺点
6.2.2 执行器项目中,开发Job方法
@Configuration
public class MyXxlJobConfig {
@XxlJob("myXxlJobConfig")
public boolean demoJobHandler() throws Exception {
XxlJobHelper.log("========myXxlJobConfig============");
System.out.println("========myXxlJobConfig============");
//ReturnT无作用
//return new ReturnT(200, "hahahahah");
return XxlJobHelper.handleSuccess("myXxlJobConfig hello world");
}
@XxlJob("myfaile")
public boolean myfaile() throws Exception {
XxlJobHelper.log("========myfaile============");
System.out.println("========myfaile============");
return XxlJobHelper.handleFail("myfaile hello world");
}
/**
* 5、生命周期任务示例:任务初始化与销毁时,支持自定义相关逻辑;init只在第一次调度时执行一次。destroy每次调度都执行
*/
@XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")
public void demoJobHandler2() throws Exception {
System.out.println("========demoJobHandler2============");
XxlJobHelper.log("XXL-JOB, Hello World.");
}
public void init() {
System.out.println("========init============");
logger.info("init");
}
public void destroy() {
System.out.println("========destory============");
logger.info("destory");
}
}
复制代码
6.2.3 调度中心,新建调度任务
注:
系统根据以下标准判断任务执行结果
仅针对执行中的任务。 在任务日志界面,点击右侧的“终止任务”按钮,将会向本次任务对应的执行器发送任务终止请求,将会终止掉本次任务,同时会清空掉整个任务执行队列。
任务终止时通过 "interrupt" 执行线程的方式实现, 将会触发 "InterruptedException" 异常。因此如果JobHandler内部catch到了该异常并消化掉的话, 任务终止功能将不可用。
因此, 如果遇到上述任务终止不可用的情况, 需要在JobHandler中应该针对 "InterruptedException" 异常进行特殊处理 (向上抛出) , 正确逻辑如下:
try{
// do something
} catch (Exception e) {
if (e instanceof InterruptedException) {
throw e;
}
logger.warn("{}", e);
}
复制代码
而且,在JobHandler中开启子线程时,子线程也不可catch处理"InterruptedException",应该主动向上抛出。
任务终止时会执行对应JobHandler的"destroy()"方法,可以借助该方法处理一些资源回收的逻辑。