1. 创建数据库
执行如下SQL语句创建相关表
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_general_ci;
use `xxl_job`;
SET NAMES utf8mb4;
CREATE TABLE `xxl_job_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_desc` varchar(255) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`author` varchar(64) DEFAULT NULL COMMENT '作者',
`alarm_email` varchar(255) DEFAULT NULL COMMENT '报警邮件',
`schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '调度类型',
`schedule_conf` varchar(128) DEFAULT NULL COMMENT '调度配置,值含义取决于调度类型',
`misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '调度过期策略',
`executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '执行器路由策略',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞处理策略',
`executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任务执行超时时间,单位秒',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`glue_type` varchar(50) NOT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE备注',
`glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新时间',
`child_jobid` varchar(255) DEFAULT NULL COMMENT '子任务ID,多个逗号分隔',
`trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '调度状态:0-停止,1-运行',
`trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次调度时间',
`trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次调度时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址,本次执行的地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数,格式如 1/2',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_log_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime DEFAULT NULL COMMENT '调度-时间',
`running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量',
`suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量',
`fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
`glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型',
`glue_source` mediumtext COMMENT 'GLUE源代码',
`glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注',
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '账号',
`password` varchar(50) NOT NULL COMMENT '密码',
`role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL COMMENT '锁名称',
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`) VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', '');
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` ( `lock_name`) VALUES ( 'schedule_lock');
commit;
各表作用如下
- xxl_job_lock:任务调度锁表;
- xxl_job_group:执行器信息表,维护任务执行器信息;
- xxl_job_info:调度扩展信息表: 用于保存XXL-JOB调度任务的扩展信息,如任务分组、任务名、机器地址、执行器、执行入参和报警邮件等等;
- xxl_job_log:调度日志表: 用于保存XXL-JOB任务调度的历史信息,如调度结果、执行结果、调度入参、调度机器和执行器等等;
- xxl_job_log_report:调度日志报表:用户存储XXL-JOB任务调度日志的报表,调度中心报表功能页面会用到;
- xxl_job_logglue:任务GLUE日志:用于保存GLUE更新历史,用于支持GLUE的版本回溯功能;
- xxl_job_registry:执行器注册表,维护在线的执行器和调度中心机器地址信息;
- xxl_job_user:系统用户表;
2. Docker配置xxl-job-admin
2.1 拉取镜像
执行命令:
docker pull xuxueli/xxl-job-admin:2.4.0
2.2 创建容器并运行
执行命令:
docker run -d -e PARAMS="--spring.datasource.url=jdbc:mysql://192.168.150.101:3306/xxl_job?Unicode=true&characterEncoding=UTF-8 --spring.datasource.username=root --spring.datasource.password=123 --xxl.job.accessToken=tianji" \
-p 28080:8080 \
-v /usr/local/src/docker/xxl-job/applogs:/data/applogs \
--name my-xxl-job \
--privileged=true \
xuxueli/xxl-job-admin:2.4.0
如果启动失败,检查数据源配置是否有效、端口是否被占用等;
参数说明:
-e PARAMS
:MySQL数据源;--privileged=true
:容器内的root拥有真正的root权限;--restart=always
:Docker服务启动时容器也随之启动;-v
:日志目录挂载;-p
:端口 左边宿主机 右边容器 ;--xxl.job.accessToken
:执行器通讯TOKEN,要和调度中心服务部署配置的accessToken一致,要不然无法连接注册。
在浏览器访问地址:http://192.168.150.101:28080/xxl-job-admin
这里的192.168.150.101
是安装xxl-job-admin的设备ip,记得防火墙开放端口;
默认的账密:admin/123456
3. SpringBoot整合xxl-job
3.1 修改YML配置文件
在application.yml配置文件添加如下内容:
tj:
xxl-job:
admin:
# 调度中心服务部署的地址
addresses: http://192.168.150.101:28080/xxl-job-admin
# 执行器通讯TOKEN,要和调度中心服务部署配置的accessToken一致,要不然无法连接注册
accessToken: tianji
executor:
# 执行器AppName
appName: xxl-job-test
# 执行器注册 [选填]
address:
ip:
#执行器端口号: 小于等于0则自动获取 默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
port: 0
# 执行器运行日志文件存储磁盘路径 [选填] 需要对该路径拥有读写权限;为空则使用默认路径;
logPath: D:/test
# 执行器日志文件保存天数 [选填] 过期日志自动清理, 限制值大于等于3时生效 否则, 如-1, 关闭自动清理功能
logRetentionDays: 15
3.2 代码整合
引入依赖,版本需要与xxl-job-admin一致:
<!--xxl-job-->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0</version>
</dependency>
配置xxl-job:
新建XxlJobProperties.java
,用于读取yml配置
package com.example.xxljobdemo.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "tj.xxl-job")
public class XxlJobProperties {
private String accessToken;
private Admin admin;
private Executor executor;
@Data
public static class Admin {
private String addresses;
}
@Data
public static class Executor {
private String appName;
private String address;
private String ip;
private Integer port;
private String logPath;
private Integer logRetentionDays;
}
}
新建XxlJobProperties.java
,用于新增xxl-job执行器
package com.example.xxljobdemo.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
@Slf4j
@Configuration
@EnableConfigurationProperties(XxlJobProperties.class)
public class XxlJobConfig {
@Bean
public XxlJobSpringExecutor xxlJobExecutor(XxlJobProperties prop) {
log.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
XxlJobProperties.Admin admin = prop.getAdmin();
if (admin != null && StringUtils.hasLength(admin.getAddresses())) {
xxlJobSpringExecutor.setAdminAddresses(admin.getAddresses());
}
XxlJobProperties.Executor executor = prop.getExecutor();
if (executor != null) {
if (executor.getAppName() != null)
xxlJobSpringExecutor.setAppname(executor.getAppName());
if (executor.getIp() != null)
xxlJobSpringExecutor.setIp(executor.getIp());
if (executor.getPort() != null)
xxlJobSpringExecutor.setPort(executor.getPort());
if (executor.getLogPath() != null)
xxlJobSpringExecutor.setLogPath(executor.getLogPath());
if (executor.getLogRetentionDays() != null)
xxlJobSpringExecutor.setLogRetentionDays(executor.getLogRetentionDays());
}
if (prop.getAccessToken() != null)
xxlJobSpringExecutor.setAccessToken(prop.getAccessToken());
log.info(">>>>>>>>>>> xxl-job config end.");
return xxlJobSpringExecutor;
}
}
3.3 建立测试任务
package com.example.xxljobdemo.task;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.stereotype.Component;
/**
* @author: hong.jian
* @date 2024-03-27 20:17
*/
@Component
public class XxlJobTask {
@XxlJob("testXxlJobHandler")
public void testXxlJobHandler() throws Exception {
System.out.println("hello---->xxl-job");
}
}
启动springboot项目,在xxl-job-admin执行器管理
手动新增执行器,因为xxl-job不会自动新增
执行器,名称要与yml配置文件中的appName
一致,这里我写的xxl-job-test;
新建成功后,等一会,点击查看能看到注册成功了
在xxl-job-admin执行器管理
手动新增任务,
其中比较关键的几个配置:
- 调度配置:也就是什么时候执行,一般选择cron表达式
- 任务配置:采用BEAN模式,指定
JobHandler
,这里指定的就是在项目中@XxlJob
注解中的任务名称 - 路由策略:就是指如果有多个任务执行器,该由谁执行?这里支持的策略非常多:
路由策略说明:
- FIRST(第一个):固定选择第一个执行器;
- LAST(最后一个):固定选择最后一个执行器;
- ROUND(轮询):在线的执行器按照轮询策略选择一个执行
- RANDOM(随机):随机选择在线的执行器;
- CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台执行器,且所有任务均匀散列在不同执行器上。
- LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的执行器优先被选举;
- LEAST_RECENTLY_USED(最近最久未使用):最久未使用的执行器优先被选举;
- FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的执行器选定为目标执行器并发起调度;
- BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的执行器选定为目标执行器并发起调度;
- SHARDING_BROADCAST(分片广播):广播触发对应集群中所有执行器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务
3.4 测试
点击操作-执行一次
,进行测试
在调度日志
界面可以看到执行成功
如果执行失败,可以在此查看错误信息方便排查
4. 总结
xxl-job需要手动新增执行器和任务,踩坑