1. XXL-JOB 简介
XXL-JOB 是一个分布式任务调度平台, 其核心设计目标是开发迅速, 学习简单, 轻量级, 易扩展. 现已开放源代码并接入多家公司线上产品线, 开箱即用. 它的有两个核心模块, 一个模块叫做调度中心, 另外一个模块叫做执行器, 它把任务调度和任务执行分成两个部分. 这样调度模块只需要负责任务的调度属性, 触发调度信号. 执行模块只需要接收调度信号, 去执行具体的业务逻辑, 两者可以各自的进行扩容和缩容. 图 1 是一张来自官方的架构图.
2. XXL-JOB 搭建
既然是一个分布式调度平台, 肯定会有一个调度中心, 当然执行器 (被调度者) 也是必不可少的, 可以参考架构图. 所以, 使用 xxl-job 搭建一个 demo, 也必须有两个端, 下面本文分别从准备工作, 搭建 "调度中心", 搭建 "执行器" 三个部分进行说明.
2.1 准备工作
2.1.1 下载源码
源码地址: https://github.com/xuxueli/xxl-job
我使用的源码是 2.2.0 版本, 这是目前最新的 release 版本.
源码包含了文档(数据库初始化脚本, 官方文档, 架构图等), 调度中心源码, 核心 core, 各个版本的执行器源码. 如图 2 所示:
2.1.2 数据库准备
数据库脚本在 doc 路径下, 将其执行之后可以创建一个数据库, 如图 3 所示:
2.2 搭建调度中心
2.2.1 配置调度中心
将数据库连接信息和报警信息配置成自己的, 配置文件如下:
- ### web
- server.port=8080
- server.servlet.context-path=/xxl-job-admin
- ### actuator
- management.server.servlet.context-path=/actuator
- management.health.mail.enabled=false
- ### resources
- spring.mvc.servlet.load-on-startup=0
- spring.mvc.static-path-pattern=/static/**
- spring.resources.static-locations=classpath:/static/
- ### freemarker
- spring.freemarker.templateLoaderPath=classpath:/templates/
- spring.freemarker.suffix=.ftl
- spring.freemarker.charset=UTF-8
- spring.freemarker.request-context-attribute=request
- spring.freemarker.settings.number_format=0.##########
- ### mybatis
- mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml
- #mybatis.type-aliases-package=com.xxl.job.admin.core.model
- ### xxl-job, datasource
- 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=123456
- spring.datasource.driver-class-name=com.MySQL.cj.jdbc.Driver
- ### datasource-pool
- spring.datasource.type=com.zaxxer.hikari.HikariDataSource
- spring.datasource.hikari.minimum-idle=10
- spring.datasource.hikari.maximum-pool-size=30
- spring.datasource.hikari.auto-commit=true
- spring.datasource.hikari.idle-timeout=30000
- spring.datasource.hikari.pool-name=HikariCP
- spring.datasource.hikari.max-lifetime=900000
- spring.datasource.hikari.connection-timeout=10000
- spring.datasource.hikari.connection-test-query=SELECT 1
- ### xxl-job, email
- 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
- ### xxl-job, access token
- xxl.job.accessToken=
- ### xxl-job, I18N (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en")
- xxl.job.I18N=zh_CN
- ## xxl-job, triggerpool max size
- xxl.job.triggerpool.fast.max=200
- xxl.job.triggerpool.slow.max=100
- ### xxl-job, log retention days
- xxl.job.logretentiondays=30
- 2.2.2 启动调度中心
- 在 IDEA 里面直接运行, 如果使用的是 macOS 系统的话, 可能会出现错误: Failed to create parent directories for [/data/applogs/xxl-job/xxl-job-admin.log], 如图 4 所示:
- 解决办法是: 将 logback.xml 中的 "/data/applogs/xxl-job/xxl-job-admin.log" 改为 "./data/applogs/xxl-job/xxl-job-admin.log", 如图 5 所示. 后续在测试运行的时候, 执行器端会抛出类似异常, 用同样的方式可以解决.
- 启动之后浏览器访问 http://localhost:8080/xxl-job-admin, 使用默认的用户名 (admin) 和密码 (123456) 登陆之后, 可以看到如图 6 所示页面:
- 2.3 搭建 "执行器"
- 2.3.1 新建执行器项目
- 使用 IDEA 新建一个 Spring Boot 项目: xxl-job-executor
- 2.3.2 添加相关依赖和配置执行器
- Maven 依赖:
- <dependency>
- <groupId>com.xuxueli</groupId>
- <artifactId>xxl-job-core</artifactId>
- <version>2.2.0</version>
- </dependency>
- 主要需要配置 xxl-job 的调度中心地址信息, xxl-job 执行器相关信息. 配置文件如下:
- # Web port
- server.port=8081
- # no Web
- #spring.main.Web-environment=false
- # log config
- logging.config=classpath:logback.xml
- ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
- xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
- ### xxl-job, access token
- xxl.job.accessToken=
- ### xxl-job executor appname
- xxl.job.executor.appname=xxl-job-executor-test
- ### 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=
- xxl.job.executor.port=9999
- ### xxl-job executor log-path
- xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
- ### xxl-job executor log-retention-days
- xxl.job.executor.logretentiondays=30
- 还要创建一个 XxlJobConfig.java 配置执行器. 代码如下:
- @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;
- }
- }
- 当然还要添加 logback.xml 文件.
- 2.3.3 编写执行器
- 在 Spring Bean 实例中, 开发 Job 方法, 方式格式要求为 "public ReturnT execute(String param)"
- 为 Job 方法添加注解 "@XxlJob(value=" 自定义 jobhandler 名称 ", init ="JobHandler 初始化方法 ", destroy ="JobHandler 销毁方法 ")", 注解 value 值对应的是调度中心新建任务的 JobHandler 属性的值. 之前的 2.1.0 版本中不支持在方法上面添加注解, 需要在类上面添加 @JobHandler 注解, 并继承 IJobHandler.
- 执行日志: 需要通过 "XxlJobLogger.log" 打印执行日志;
- 代码如下:
- @Component
- public class TestXxlJobHandler {
- private static Logger logger = LoggerFactory.getLogger(TestXxlJobHandler.class);
- /**
- * 1, 简单任务示例(Bean 模式)
- */
- @XxlJob("testJobHandler")
- public ReturnT<String> demoJobHandler(String param) throws Exception {
- System.out.println(new Date() + "Test Xxl-Job~");
- return ReturnT.SUCCESS;
- }
- }
完成之后的整个代码结构如图 8 所示:
3. 测试
在本机运行调度中心和执行器.
3.1 新增执行器
在调度中心新增一个测试执行器, AppName 为 xxl-job-executor-test, 名称为测试执行器, 注册方式选择自行注册即可, 如图 9 所示:
3.2 新增任务
3.2.1 新增任务
新增一个任务, 名称与代码中名称一致, 配置为每 2 分钟执行一次, 路由策略为一致性 HASH, 运行模式为 BEAN, 阻塞处理策略为单机串行, 配置如图 10 所示:
3.2.2 配置属性
详细配置属性可以参考:
● 执行器: 任务的绑定的执行器, 任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组. 每个任务必须绑定一个执行器, 可在 "执行器管理" 进行设置;
● 任务描述: 任务的描述信息, 便于任务管理;
● 路由策略: 当执行器集群部署时, 提供丰富的路由策略, 包括;
FIRST(第一个): 固定选择第一个机器;
LAST(最后一个): 固定选择最后一个机器;
ROUND(轮询):;
RANDOM(随机): 随机选择在线的机器;
CONSISTENT_HASH(一致性 HASH): 每个任务按照 Hash 算法固定选择某一台机器, 且所有任务均匀散列在不同机器上.
LEAST_FREQUENTLY_USED(最不经常使用): 使用频率最低的机器优先被选举;
LEAST_RECENTLY_USED(最近最久未使用): 最久未使用的机器优先被选举;
FAILOVER(故障转移): 按照顺序依次进行心跳检测, 第一个心跳检测成功的机器选定为目标执行器并发起调度;
BUSYOVER(忙碌转移): 按照顺序依次进行空闲检测, 第一个空闲检测成功的机器选定为目标执行器并发起调度;
SHARDING_BROADCAST(分片广播): 广播触发对应集群中所有机器执行一次任务, 同时系统自动传递分片参数; 可根据分片参数开发分片任务;
● Cron: 触发任务执行的 Cron 表达式;
● 运行模式:
BEAN 模式: 任务以 JobHandler 方式维护在执行器端; 需要结合 "JobHandler" 属性匹配执行器中任务;
GLUE 模式(Java): 任务以源码方式维护在调度中心; 该模式的任务实际上是一段继承自 IJobHandler 的 Java 类代码并 "groovy" 源码方式维护, 它在执行器项目中运行, 可使用 @Resource/@Autowire 注入执行器里中的其他服务;
GLUE 模式(Shell): 任务以源码方式维护在调度中心; 该模式的任务实际上是一段 "shell" 脚本;
GLUE 模式(Python): 任务以源码方式维护在调度中心; 该模式的任务实际上是一段 "python" 脚本;
GLUE 模式(PHP): 任务以源码方式维护在调度中心; 该模式的任务实际上是一段 "php" 脚本;
GLUE 模式(Node.JS): 任务以源码方式维护在调度中心; 该模式的任务实际上是一段 "nodejs" 脚本;
GLUE 模式(PowerShell): 任务以源码方式维护在调度中心; 该模式的任务实际上是一段 "PowerShell" 脚本;
● JobHandler: 运行模式为 "BEAN 模式" 时生效, 对应执行器中新开发的 JobHandler 类 "@JobHandler" 注解自定义的 value 值;
● 阻塞处理策略: 调度过于密集执行器来不及处理时的处理策略;
单机串行(默认): 调度请求进入单机执行器后, 调度请求进入 FIFO 队列并以串行方式运行;
丢弃后续调度: 调度请求进入单机执行器后, 发现执行器存在运行的调度任务, 本次请求将会被丢弃并标记为失败;
覆盖之前调度: 调度请求进入单机执行器后, 发现执行器存在运行的调度任务, 将会终止运行中的调度任务并清空队列, 然后运行本地调度任务;
● 子任务: 每个任务都拥有一个唯一的任务 ID(任务 ID 可以从任务列表获取), 当本任务执行结束并且执行成功时, 将会触发子任务 ID 所对应的任务的一次主动调度.
● 任务超时时间: 支持自定义任务超时时间, 任务运行超时将会主动中断任务;
● 失败重试次数; 支持自定义任务失败重试次数, 当任务失败时将会按照预设的失败重试次数主动进行重试;
● 报警邮件: 任务调度失败时邮件通知的邮箱地址, 支持配置多邮箱地址, 配置多个邮箱地址时用逗号分隔;
● 负责人: 任务的负责人;
● 执行参数: 任务执行所需的参数;
3.3 启动任务测试
启动调度任务, 如图 11 所示:
可以查看日志或者控制台信息, 运行结果满意, 如图 12 所示:
在控制台运行报表界面也可以看到调度和执行情况, 如图 13 所示. 图中那一次调度失败是由于执行器重启, 造成了调度中心调度任务的时候发现调度地址为空, 所以执行失败.
参考文档: 官方中文文档 https://www.xuxueli.com/xxl-job/
来源: https://www.cnblogs.com/sgh1023/p/13289968.html