xxl-job分布式任务调度
⼀个分布式的任务调度框架,官⽹⽂档写的⾮常详细,只是简单的记录下。
1. 部署admin项⽬
admin项⽬是⼀个可视化管理控制的项⽬。
1.下载
2.到数据库执⾏脚本
/xxl-job/doc/db/tables_xxl_job.sql
3.编译源码
xxl-job-admin:调度中⼼
xxl-job-core:公共依赖
xxl-job-executor-samples:执⾏器Sample⽰例(选择合适的版本执⾏器,可直接使⽤,也可以参考其并将现有项⽬改造成执⾏器)
:xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执⾏器,推荐这种⽅式;
:xxl-job-executor-sample-spring:Spring版本,通过Spring容器管理执⾏器,⽐较通⽤;
:xxl-job-executor-sample-frameless:⽆框架版本;
:xxl-job-executor-sample-jfinal:JFinal版本,通过JFinal管理执⾏器;
:xxl-job-executor-sample-nutz:Nutz版本,通过Nutz管理执⾏器;
:xxl-job-executor-sample-jboot:jboot版本,通过jboot管理执⾏器;
4.配置调度中⼼
xxl-job-admin 是项⽬的配置中⼼。导⼊IDEA,maven环境配置好之后启动是⾮常⽅便的。
1. 需要改⼀下数据库的连接信息
2.启动主类
3.启动后访问8080端⼝就可以
4.登录账号密码是 admin/123456
5.界⾯如下:
2. 配置项⽬执⾏器项⽬
这个就是实际⼯作的项⽬。这个是xxl-job⾃带的项⽬。
1.启动xxl-job-executor-sample-springboot 项⽬
2. 控制台执⾏
3. 启动后从admin管理项⽬运⾏⼀次
到任务管理执⾏⼀次即可。
4.查看启动⽇志
2020-11-1514:09:00 [hread.JobThread#run]-[130]-[Thread-39]
----------- xxl-job job execute start -----------
-
---------- Param:
2020-11-1514:09:00 [utor.service.jobhandler.SampleXxlJob#demoJobHandler]-[39]-[Thread-39] XXL-JOB, Hello World. 2020-11-1514:09:00 [utor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:0
2020-11-1514:09:02 [utor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:1
2020-11-1514:09:04 [utor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:2
2020-11-1514:09:06 [utor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:3
2020-11-1514:09:08 [utor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:4
2020-11-1514:09:10 [hread.JobThread#run]-[176]-[Thread-39]
----------- xxl-job job execute end(finish) -----------
----------- Result: handleCode=200, handleMsg = null
2020-11-1514:09:10 [hread.TriggerCallbackThread#callbackLog]-[197]-[xxl-job, executor TriggerCallbackThread]
----------- xxl-job job callback finish.
[Load Log Finish]
3 .模仿上⾯项⽬⾃建任务在Springboot中运⾏
1.新建项⽬cloud-xxl-job-8081
2.修改pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="/POM/4.0.0"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud</artifactId>
<groupId>cn.qz.cloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-xxl-job-8081</artifactId>
<dependencies>
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.2.0</version>
</dependency>
<!--引⼊⾃⼰抽取的⼯具包-->
<dependency>
<groupId>cn.qz.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3. 新增application.properties
# web port
server.port=8081
# no web
#spring.main.web-environment=false
# log config
### xxl-job admin address list, such as "address" or "address01,address02"
xxl.job.admin.addresses=127.0.0.1:8080/xxl-job-admin
### xxl-job, access token
xxl.job.accessToken=
### xxl-job executor appname
utor.appname=xxl-job-executor-test
### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
utor.address=
### xxl-job executor server-info
utor.ip=
utor.port=9999
### xxl-job executor log-path
utor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job executor log-retention-days
utor.logretentiondays=30
关于配置的详细解释如下:
### 调度中⼼部署跟地址 [选填]:如调度中⼼集部署存在多个地址则⽤逗号分隔。执⾏器将会使⽤该地址进⾏"执⾏器⼼跳注册"和"任务结果回调";为空则关闭⾃动注册;xxl.job.admin.addresses=127.0.0.1:8080/xxl-job-admin
### 执⾏器通讯TOKEN [选填]:⾮空时启⽤;
xxl.job.accessToken=
### 执⾏器AppName [选填]:执⾏器⼼跳注册分组依据;为空则关闭⾃动注册
utor.appname=xxl-job-executor-sample
### 执⾏器注册 [选填]:优先使⽤该配置作为注册地址,为空时使⽤内嵌服务 ”IP:PORT“ 作为注册地址。从⽽更灵活的⽀持容器类型执⾏器动态IP和动态映射端⼝问题。utor.address=
### 执⾏器IP [选填]:默认为空表⽰⾃动获取IP,多⽹卡时可⼿动设置指定IP,该IP不会绑定Host仅作为通讯实⽤;地址信息⽤于 "执⾏器注册" 和 "调度中⼼请求并触发任务";utor.ip=
### 执⾏器端⼝号 [选填]:⼩于等于0则⾃动获取;默认端⼝为9999,单机部署多个执⾏器时,注意要配置不同执⾏器端⼝;
utor.port=9999
### 执⾏器运⾏⽇志⽂件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使⽤默认路径;
utor.logpath=/data/applogs/xxl-job/jobhandler
### 执⾏器⽇志⽂件保存天数 [选填] :过期⽇志⾃动清理, 限制值⼤于等于3时⽣效; 否则, 如-1, 关闭⾃动清理功能;
utor.logretentiondays=30
4. 主启动类
package cn.qz.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author: qlq
* @Description
* @Date: 14:44 2020/11/15
*/
@SpringBootApplication
public class XXLJobMain8081 {
public static void main(String[] args) {
SpringApplication.run(XXLJobMain8081.class, args);
}
}
5.业务类
有两种⽅式。第⼀种是基于⽅法上⾯增加注解@XxlJob;第⼆种是类继承IJobHandler,然后通过⼿动注⼊到执⾏器容器。
(1) ⽅法加注解 @XxlJob 实现
package cn.qz.cloud.job;
del.ReturnT;
handler.annotation.XxlJob;
log.XxlJobLogger;
slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @Author: qlq
* @Description
* @Date: 15:22 2020/11/15
*/
@Slf4j
@Component
public class FirstJob {
@XxlJob(value = "firstJob", init = "init", destroy = "destroy")
public ReturnT<String> execute(String param) {
XxlJobLogger.log("XXL-JOB, firstJob. param: {}", param);
log.info("XXL-JOB, firstJob. param: {}", param);
return ReturnT.SUCCESS;
}
public void init() {
log.info("init");
}
public void destroy() {
log.info("destory");
}
}
XxlJobLogger.log是记录到xxl-job-admin 的⽇志收集器⾥⾯,可以从admin管理台查看;普通的log记录是记录到我们系统的⽇志搜集器⾥⾯。
(2) 继承IJobHandler的⽅式
package cn.qz.cloud.job;
del.ReturnT;
handler.IJobHandler;
log.XxlJobLogger;
slf4j.Slf4j;
import urrent.TimeUnit;
/**
* @Author: qlq
* @Description
* @Date: 15:22 2020/11/15
*/
@Slf4j
public class XXLClassJob extends IJobHandler {
@Override
public ReturnT<String> execute(String param) throws Exception {
log.info("XXLClassJob execute, param: {}", param);
XxlJobLogger.log("XXLClassJob execute, param: {}", param);
for (int i = 0; i < 5; i++) {
log.info("XXLClassJob start, i: {} ", i);
XxlJobLogger.log("XXLClassJob start, i: {} ", i);
TimeUnit.SECONDS.sleep(2);
}
return ReturnT.SUCCESS;
}
}
(3) 配置类:注意需要⼿动将job注⼊到执⾏器容器
package cn.fig;
import cn.qz.cloud.job.XXLClassJob;
xecutor.XxlJobExecutor;
xecutor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import t.annotation.Bean;
import t.annotation.Configuration;
/**
* @Author: qlq
* @Description
* @Date: 17:02 2020/11/15
*/
@Configuration
public class XxlJobConfig {
private Logger logger = Logger(XxlJobConfig.class);
static {
// ⼿动通过如下⽅式注⼊到执⾏器容器。
}
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${utor.appname}")
private String appname;
@Value("${utor.address}")
private String address;
@Value("${utor.ip}")
private String ip;
@Value("${utor.port}")
private int port;
@Value("${utor.logpath}")
private String logPath;
@Value("${utor.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;
}
}
6. 启动主类
20:46:27.096 logback [main] INFO http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8081"]
20:46:27.238 logback [main] INFO o.s.at.TomcatWebServer - Tomcat started on port(s): 8081 (http) with context path ''
20:46:27.252 logback [main] INFO cn.qz.cloud.XXLJobMain8081 - Started XXLJobMain8081 in 20.195 seconds (JVM running for 23.668)
20:46:37.301 logback [Thread-5] INFO server.EmbedServer - >>>>>>>>>>> xxl-job remoting server start success, nettype = server.EmbedServer, 20:47:00.694 logback [xxl-rpc, EmbedServer bizThreadPool-1961798941] INFO c.xecutor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:4, handler:com 20:47:00.695 logback [Thread-8] INFO cn.qz.cloud.job.FirstJob - init
20:47:00.715 logback [xxl-rpc, EmbedServer bizThreadPool-1961798941] INFO c.xecutor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:5, handler:cn.可以看到启动了⼀个内嵌的服务9999端⼝。通过netstat -ano 也可以查看9999端⼝,如果之后测试报错可以查看是否没有监听到某个端⼝。
7.在xxl-job-admin 界⾯进⾏设置
(1) 新建⼀个执⾏器
(2) 新建⼀个任务管理执⾏XXLClassJob 任务
(3)新建⼀个任务执⾏firstJob
(4) 任务管理 -》选择⼀条任务之后执⾏⼀次 firstJob
到IDEA查看⽇志如下:
21:06:27.977 logback [xxl-rpc, EmbedServer bizThreadPool-1916408283] INFO c.xecutor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:4, handler:com 21:06:27.983 logback [Thread-8] INFO cn.qz.cloud.job.FirstJob - init
21:06:28.007 logback [Thread-8] INFO cn.qz.cloud.job.FirstJob - XXL-JOB, firstJob. param: XXX
然后可以到XxlJob-admin查看⽇志:
2020-11-15 21:06:27 [hread.JobThread#run]-[124]-[Thread-8]
----------- xxl-job job execute start -----------
----------- Param:XXX
2020-11-15 21:06:28 [cn.qz.cloud.job.FirstJob#execute]-[20]-[Thread-8] XXL-JOB, firstJob. param: XX
X
2020-11-15 21:06:28 [hread.JobThread#run]-[164]-[Thread-8]
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-11-15 21:06:28 [hread.TriggerCallbackThread#callbackLog]-[191]-[xxl-job, executor TriggerCallbackThread]
----------- xxl-job job callback finish.
8. 简单的测下分布式环境控制哪个机器执⾏任务
1. 再启动⼀个执⾏项⽬,项⽬端⼝8082;utor.port 改为9998
2. 从admin查看机器地址有两个,如下:
3. 编辑任务可以看到有好⼏种策略。这些策略是说从哪个机器执⾏上⾯的任务,类似于⼀个应该多实例部署,我们可以⼿动设置哪个实例执⾏任务。有点类似于负载均衡。
4.我们改为轮询即可,可以通过执⾏⽇志查看到是两个机器替换着执⾏
9. GLUE模式(Java) 简单使⽤
上⾯的模式可以称为Bean模式,符合常见的开发思想。
“GLUE模式(Java)”的执⾏代码托管到调度中⼼在线维护,相⽐“Bean模式任务”需要在执⾏器项⽬开发部署上线,更加简便轻量),可使⽤@Resource/@Autowire注⼊执⾏器⾥中的其他服务。前提是“调度中⼼”和“执⾏器”项⽬已经成功部署并启动。这种模式实现是利⽤groovy将类信息加载到JVM中。
1.新建⼀个任务管理,模式选择GLUE
2. 任务管理选择⼀条任务操作-》 GLUE IDE,代码如下:
package cn.qz.cloud.job;
del.ReturnT;
handler.IJobHandler;
log.XxlJobLogger;
slf4j.Slf4j;
import urrent.TimeUnit;
/**
* @Author: qlq
* @Description
* @Date: 15:22 2020/11/15
*/
public class XXLClassJob2 extends IJobHandler {
@Override
public ReturnT<String> execute(String param) throws Exception {
System.out.println("param : " + param);
XxlJobLogger.log("XXLClassJob2 execute, param: {}", param);
for (int i = 0; i < 5; i++) {
XxlJobLogger.log("XXLClassJob2 Glue start, i: {} ", i);
TimeUnit.SECONDS.sleep(2);
}
return ReturnT.SUCCESS;
}
}
3.执⾏⼀次后可以到IDEA查看⽇志,同时查看执⾏⽇志如下:
2020-11-15 21:42:59 [hread.JobThread#run]-[124]-[Thread-15]
----------- xxl-job job execute start -----------
-
---------- Param:这是Glue参数
2020-11-15 21:42:59 [handler.impl.GlueJobHandler#execute]-[26]-[Thread-15] ----------- glue.version:1605447731000 -----------
2020-11-15 21:42:59 [flect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 execute, param: 这是Glue参数
2020-11-15 21:42:59 [flect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 0
2020-11-15 21:43:01 [flect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 1
2020-11-15 21:43:03 [flect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 2
2020-11-15 21:43:05 [flect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 3
2020-11-15 21:43:07 [flect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 4
spring framework2020-11-15 21:43:09 [hread.JobThread#run]-[164]-[Thread-15]
----------- xxl-job job execute end(finish) -----------
----------- ReturnT:ReturnT [code=200, msg=null, content=null]
2020-11-15 21:43:09 [hread.TriggerCallbackThread#callbackLog]-[191]-[xxl-job, executor TriggerCallbackThread]
----------- xxl-job job callback finish.
⾄此简单的实现了分布式环境下的任务调度。当任务在多个实例部署的时候,可以在xxl-job的管理界⾯选择执⾏任务的机器。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论