1. 概述
XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
github地址:https://github.com/xuxueli/xxl-job
官方文档:http://www.xuxueli.com/xxl-job/#/
2. 架构图
步骤:
① 部署:xxl-job-admin 作为注册中心
② 创建执行器(具体调度地址) 可以支持集群
③ 配置文件需要填写xxl-job注册中心地址
④ 每个具体执行job服务器需要创建一个netty连接端口号
⑤ 需要执行job的任务类,集成IJobHandler抽象类注册到job容器中
⑥ Execute方法中编写具体job任务
核心:
任务调度平台根据执行地址,转发到真实执行器。
3. 原理
首先要搭建一个xxl-job平台,在平台创建一个执行器,创建执行器的时候,netty会帮你创建一个端口号,
执行器启动的时候,会把服务器信息注册到xxl-job平台。
在xxl-job平台创建任务管理,任务管理核心参数有执行器,JobHandler(对应代码中@JobHandler的value名称),Cron表达式
首先会在xxl-job平台先去触发定时job,会获取到执行器对应的实际服务器地址,然后使用xxl-job发送请求到实际的定时job任务地址执行,使用demoJobHandler名称查找对应的jvm服务器上JobHandler容器获取到类的信息,再使用反射机制进行执行。
1. 首先搭建xxl-job-admin平台
下载官方demo,建好数据库,导入xxl-job-admin项目,在xxl-job-admin.properties修改几个配置,如数据源,邮箱,账号等
由于不是springboot项目,需要单独部署tomcat启动,我配的是8090端口,浏览器访问:http://localhost:8090/,默认用户名密码可以在xxl-job-admin.properties修改,登录成功后出现如下页面:
接下来配置几个东西:
① 配置执行器:点击执行器管理 -- 新增执行器 -- 填写参数保存即可
(注册方式选择手动录入,机器地址为下面客户端springboot项目yml中的xxl.job.executor.port参数)
② 新建任务:任务管理 -- 新建任务 -- 填写参数保存即可
(执行器选择上面创建的job-执行器,Cron表示每三秒执行一次,JobHandler即客户端springboot项目中@JobHandler的value)
2. 搭建客户端(即实际中我们的项目)
这里以官方demo为例:xxl-job-executor-sample-springboot
配置:
server.port=8082
logging.config=classpath:logback.xml
xxl.job.admin.addresses=http://127.0.0.1:8090/ #即xxl-job-admin的地址
xxl.job.executor.appname=job-zhaobin #创建的AppName
xxl.job.executor.ip=
xxl.job.executor.port=9092 #执行器的执行地址端口号
### xxl-job, access token
xxl.job.accessToken=
### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job log retention days
xxl.job.executor.logretentiondays=-1
编写核心定时job:
package com.xxl.job.executor.service.jobhandler;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* 任务Handler示例(Bean模式)
* 开发步骤: 1、继承"IJobHandler":“com.xxl.job.core.handler.IJobHandler”;
* 2、注册到Spring容器:添加“@Component”注解,被Spring容器扫描为Bean实例;
* 3、注册到执行器工厂:添加“@JobHandler(value="自定义jobhandler名称")”注解,
* 注解value值对应的是调度中心新建任务的JobHandler属性的值。 4、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;
*/
@JobHandler(value = "demoJobHandler")
@Component
public class DemoJobHandler extends IJobHandler {
@Value("${xxl.job.executor.port}")
private String executorPort;
// @JobHandler 底层实现 value demoJobHandler 名称 对应存放类的class地址
// com.xxl.job.executor.service.jobhandler 在使用反射机制 执行execute
// 目的是为了反射统一执行方法
@Override
public ReturnT execute(String param) throws Exception {
// 任务调度执行地址
System.out.println("####DemoJobHandler####execute()执行 executorPort:" + executorPort);
return SUCCESS;
}
}
此时,启动xxl-job-executor-sample-springboot,会发现控制台会每隔3秒打印一次
如想更改Cron规则,直接在xxl-job-admin的任务管理 - 编辑任务 - 更改Cron表达式即可。
拓展:任务管理有暂停和恢复的功能,必要时可以使用:
3. 搭建执行器集群
① 模拟集群,同时启动两个xxl-job-executor-sample-springboot,yml如下:
server.port=8081
logging.config=classpath:logback.xml
xxl.job.admin.addresses=http://127.0.0.1:8090/
### xxl-job executor address
xxl.job.executor.appname=job-zhaobin
xxl.job.executor.ip=
xxl.job.executor.port=9091
### xxl-job, access token
xxl.job.accessToken=
### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job log retention days
xxl.job.executor.logretentiondays=-1
server.port=8082
logging.config=classpath:logback.xml
xxl.job.admin.addresses=http://127.0.0.1:8090/
### xxl-job executor address
xxl.job.executor.appname=job-zhaobin
xxl.job.executor.ip=
xxl.job.executor.port=9092
### xxl-job, access token
xxl.job.accessToken=
### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### xxl-job log retention days
xxl.job.executor.logretentiondays=-1
② xxl-job-admin配置
编辑执行器,新增一个机器地址9092,逗号隔开
任务管理,路由策略改为轮训:
同时启动,可以看到8081和8082轮训执行!
1. xxl-job-admin宕机了怎么,会导致所有的任务无法执行,怎么解决? 没错,xxl-job-admin实现集群
调度中心支持集群部署,提升调度系统容灾和可用性。
调度中心集群部署时,几点要求和建议:(拷贝的官方文档)
这里以Nginx为例,首先在本机host文件配置伪域名,然后配置nginx.conf如下:
upstream backServer{
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=1;
}
server {
listen 80;
server_name xxl-job-bin.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://backServer;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
启动两个xxl-job-admin,此时,先启动8080,再启动8081,浏览器访问:xxl-job-bin.com,执行任务。点击回复/执行
会发现会一直走8081服务器,即后面启动的服务器(报错是因为找不到执行器,不用考虑):
当关闭8081,则会走8080端口去执行(符合上面图中一主一备的说法)
2. 编写完成属于自己的SpringBoot项目
首先需要把官方的demo打到本地仓库(尤其是xxl-job-core)
然后复制官方demo的以下文件:
pom如下:
4.0.0
com.example
springboot-xxl-job-demo
0.0.1-SNAPSHOT
springboot-xxl-job-demo
Demo project for Spring Boot
3.0.1
2.2
4.3.14.RELEASE
2.9.4
1.8.13
1.7.25
2.3.23
4.12
9.2.24.v20180105
4.0.51
4.5.5
1.3
4.1
3.7
1.5
0.9.5.2
5.1.45
1.3.1
3.4.5
2.4.13
2.3.0
1.5.10.RELEASE
UTF-8
UTF-8
1.8
1.9.2-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
${spring-boot.version}
pom
import
org.eclipse.jetty
jetty-server
${jetty-server.version}
org.eclipse.jetty
jetty-util
${jetty-server.version}
org.eclipse.jetty
jetty-http
${jetty-server.version}
org.eclipse.jetty
jetty-io
${jetty-server.version}
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
com.xuxueli
xxl-job-core
1.9.2-SNAPSHOT
org.springframework.boot
spring-boot-maven-plugin
注意官方demo中不用parent的方式引入springboot版本,而是直接在一个
新建job:
package com.example.job;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@JobHandler("myJob")
public class MyJob extends IJobHandler {
@Value("${server.port}")
private String serverPort;
@Override
public ReturnT execute(String param) throws Exception {
System.out.println("xxl-job传递参数param:" + param);
return SUCCESS;
}
}
注意:@JobHandler("myJob")的value要与任务管理的JobHandler一致
application.peoperties配置如下:
server.port=8082
logging.config=classpath:logback.xml
xxl.job.admin.addresses=http://127.0.0.1:8080/
xxl.job.executor.appname=job-zhaobin
xxl.job.executor.ip=
xxl.job.executor.port=9091
xxl.job.accessToken=
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
xxl.job.executor.logretentiondays=-1
注意:appname和xxl执行端口要和下图一致:
此时,启动xxl-job-admin,启动springboot项目,修改参数分别为hahaha和xixixi,cron为2秒执行一次:
可以看到后台打印日志:
至此,分布式任务调度平台xxl-job正式搭建并整合完毕!
补充知识:
1. 常用的路由策略:
① 故障转移:会一直走第一个,当第一个挂了,会走第二个(即一主一备)
② 分片广播:第一个和第二个会一起执行(不推荐,job会重复执行)
③ 第一个和最后一个:会一直在第一个和最后一个执行
④ 轮训:类似nginx轮训机制
2. 如果第一次job没有执行完毕,第二次还会执行吗? 会执行
3. 任务超时时间:任务在规定时间内没有完成的情况下,就会进行重试
阻塞处理策略:选择单机串行即可