XXL-JOB

概述

XXL-JOB 是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。

中文文档:https://www.xuxueli.com/xxl-job/

设计思想

设计思想是将调度行为抽象形成调度中心公共平台,平台本身不承担业务逻辑,而是负责发起调度请求后,由执行器接收调度请求并执行任务,这里的任务抽象为分散的 JobHandler,交由执行器统一管理。通过这种方式即可实现调度任务相互解藕,从而提高系统整体的稳定性和拓展性。

系统组成

  • 调度模块(调度中心)
    负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块;
    支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,GLUE开发和任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover。
  • 执行模块(执行器)
    负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效;
    接收“调度中心”的执行请求、终止请求和日志请求等。

架构

image-20230503005646974

特性

image-20230503005136536

分布式任务调度平台

分布式下,每个服务都可以搭建为集群,这样的好处是可以将任务切片分给每一个服务从而实现并行执行,提高任务调度的处理效率。

在集群环境下,使用单体系统的任务调度会出现很多问题:

  • 无法做到对任务的控制,避免任务的重复执行
  • 单体应用宕机会存在任务丢失
  • 无法做到弹性扩容即增加服务实例
  • 如何做到对任务调度的执行情况统一监测

部署

拉取镜像

1
docker pull xuxueli/xxl-job-admin:2.3.1

创建数据卷目录

1
mkdir -p -m 777 /mydata/xxl-job/data/applogs

SQL文件导入到指定数据库

SQL文件:https://gitee.com/xuxueli0323/xxl-job/blob/master/doc/db/tables_xxl_job.sql

image-20230503011358348

运行容器

1
2
3
4
5
docker run -p 8080:8080 --restart=always \
-e PARAMS="--spring.datasource.url=jdbc:mysql://1.117.34.49:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai --spring.datasource.username=root --spring.datasource.password=1qaz@WSX#EDC" \
-v /mydata/xxl-job/data/applogs:/data/applogs \
--name xxl-job-admin \
-d xuxueli/xxl-job-admin:2.3.1

访问任务调度平台

访问:http://1.117.34.49:8080/xxl-job-admin

image-20230503013351386

SpringBoot集成XXL-JOB

XXL-JOB由调度中心执行器组成,上面部署了调度中心,下面介绍如何配置部署执行器。

导入依赖

1
2
3
4
5
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.1</version>
</dependency>

配置application.yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
xxl:
job:
admin:
# 指定调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册
address: http://1.117.34.49:8080/xxl-job-admin
# 执行器通讯TOKEN [选填]:非空时启用
access-token: default_token
executor:
# 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
app-name: spring-demo-xxl-job-executor
# 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题
address:
# 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务"
ip:
# 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口(执行器实际上是一个内嵌的服务,默认端口9999,配置多个同一服务实例时需要指定不同的执行器端口,否则会端口冲突)
port: 9999
# 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径
log-path: /data/applogs/xxl-job/jobhandler
# 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能
log-retention-days: -1

编辑配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Data
@Configuration
@ConfigurationProperties(prefix = "xxl.job")
public class XxlJobProps {
/**
* 调度中心配置
*/
private XxlJobAdminProps admin;

/**
* 执行器配置
*/
private XxlJobExecutorProps executor;

/**
* 与调度中心交互的accessToken
*/
private String accessToken;

@Data
public static class XxlJobAdminProps {
/**
* 调度中心地址
*/
private String address;
}

@Data
public static class XxlJobExecutorProps {
/**
* 执行器名称
*/
private String appName;

/**
* 执行器 IP
*/
private String ip;

/**
* 执行器端口
*/
private int port;

/**
* 执行器日志位置
*/
private String logPath;

/**
* 执行器日志保留天数
*/
private int logRetentionDays;
}
}

调度中心新增执行器

image-20230503045053765

执行器的配置属性:

  • AppName: 每个执行器集群的唯一标示 AppName,执行器会周期性以 AppName 为对象进行自动注册。可通过该配置自动发现注册成功的执行器,供任务调度时使用。
  • 名称:执行器的名称(可以使用中文)
  • 注册方式:调度中心获取执行器地址的方式。
    • 自动注册:执行器自动进行执行器注册,调度中心通过底层注册表可以动态发现执行器机器地址。
    • 手动录入:人工手动录入执行器的地址信息,多地址逗号分隔,供调度中心使用。
  • 机器地址:”注册方式”为”手动录入”时有效,支持人工维护执行器的地址信息。

配置执行器自定义任务:

配置自定义任务有很多种模式,包括Bean模式(基于方法)、Bean模式(基于类)、GLUE模式等。这里介绍通过Bean模式(基于方法)。

Bean模式(基于方法)就是每个任务对应一个方法,通过添加 @XxLJob(value="自定义JobHandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法") 注解完成定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Slf4j
@Component
public class DemoJob {

/**
* 基于方法注入,每个任务对应一个方法
* @XxlJob: ,注解value值对应的是调度中心新建任务的JobHandler属性的值
*
* @param param 定时任务参数
* @return 执行状态
* @throws Exception 任务异常
*/
@XxlJob(value = "demoHandler")
public void demoHandler(String param) throws Exception {
// 动态获取传递的参数(根据参数不同,当前调度的任务不同)
log.info("【param】= {}", param);
// 执行日志: 通过XxlJobHelper.log打印日志
XxlJobHelper.log("demo task run at: {}", DateUtil.now());
// 任务结果:默认任务结果为"成功"状态,不需要主动设置;可以通过XxlJobHelper.handleSuccess()/handleFail()自动设置任务结果
if (RandomUtil.randomInt(1, 11) % 2 == 0) {
XxlJobHelper.handleSuccess();
}
XxlJobHelper.handleFail();
}
}

调度中心新增任务

image.png

image-20230503045742690

任务配置属性详细说明

image-20230503045953543