SpringBoot 整合 XXL-JOB 详解
本文将详细介绍如何在 SpringBoot 项目中整合 XXL-JOB 分布式任务调度平台,包括调度中心部署、执行器配置、任务开发和管理等内容。
一、XXL-JOB 简介
XXL-JOB 是一个轻量级分布式任务调度平台,具有以下特点:
- 简单易用,学习成本低
- 功能丰富,支持多种任务调度方式
- 高可用,支持集群部署
- 丰富的监控和报警机制
- 易于扩展
二、环境准备
1. 基础环境要求
- JDK 1.8+
- Maven 3+
- MySQL 5.7+
2. 下载 XXL-JOB 源码
从官方仓库下载源码:
# GitHub
git clone https://github.com/xuxueli/xxl-job.git
# 或 Gitee
git clone http://gitee.com/xuxueli0323/xxl-job.git
# 切换到稳定版本(以2.3.0为例)
git checkout -b 2.3.0 origin/2.3.0
三、调度中心部署
1. 初始化数据库
执行源码中 /xxl-job/doc/db/tables_xxl_job.sql 脚本,创建 xxl_job 数据库和相关表。
2. 配置调度中心
修改 xxl-job-admin 模块的 application.properties 文件:
# 服务端口
server.port=8080
# 数据库连接信息
spring.datasource.url=jdbc:mysql://localhost:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 登录账号配置
xxl.job.login.username=admin
xxl.job.login.password=123456
# 调度中心通信TOKEN(可选,非空时启用)
xxl.job.accessToken=default_token
# 日志配置
logging.config=classpath:logback.xml
3. 启动调度中心
编译并启动 xxl-job-admin 项目:
cd xxl-job/xxl-job-admin
mvn clean package
java -jar target/xxl-job-admin.jar
访问 http://localhost:8080/xxl-job-admin,使用默认账号密码登录:
- 用户名:admin
- 密码:123456
四、SpringBoot 项目整合 XXL-JOB
1. 创建 SpringBoot 项目
可以使用 Spring Initializr 创建一个基础的 SpringBoot 项目。
2. 添加依赖
在项目的 pom.xml 文件中添加 XXL-JOB 依赖:
<!-- XXL-JOB 核心依赖 -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.0</version> <!-- 版本需与调度中心一致 -->
</dependency>
3. 配置文件设置
在 application.properties 或 application.yml 中配置 XXL-JOB:
application.yml 配置:
server:
port: 8081
spring:
application:
name: xxl-job-executor-sample
# XXL-JOB 配置
xxl:
job:
admin:
addresses: http://localhost:8080/xxl-job-admin # 调度中心地址
accessToken: default_token # 与调度中心的通信令牌
executor:
appname: xxl-job-executor-sample # 执行器名称
ip: # 执行器IP,默认为空自动获取
port: 9999 # 执行器端口
logpath: /data/applogs/xxl-job/jobhandler # 日志路径
logretentiondays: 30 # 日志保留天数
# 日志配置
logging:
config: classpath:logback.xml
4. 创建 XXL-JOB 配置类
package com.example.config;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@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.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.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
}
5. 创建任务处理器
创建一个任务处理器类,使用 @XxlJob 注解定义任务:
package com.example.jobhandler;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class SampleXxlJob {
private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);
/**
* 1. 简单任务示例(Bean模式)
*/
@XxlJob("demoJobHandler")
public ReturnT<String> demoJobHandler(String param) throws Exception {
logger.info("XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) {
logger.info("beat at {}, param: {}", i, param);
TimeUnit.SECONDS.sleep(2);
}
return ReturnT.SUCCESS;
}
/**
* 2. 分片广播任务
*/
@XxlJob("shardingJobHandler")
public ReturnT<String> shardingJobHandler(String param) throws Exception {
// 分片参数
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
logger.info("分片参数:当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);
// 业务逻辑
for (int i = 0; i < 5; i++) {
logger.info("第 {} 片, 第 {} 次任务执行", shardIndex, i);
TimeUnit.SECONDS.sleep(1);
}
return ReturnT.SUCCESS;
}
/**
* 3. 命令行任务
*/
@XxlJob("commandJobHandler")
public ReturnT<String> commandJobHandler(String param) throws Exception {
String command = param;
if (command == null || command.trim().length() == 0) {
command = "echo 'hello xxl-job'";
}
Process process = Runtime.getRuntime().exec(command);
String result = IOUtils.toString(process.getInputStream(), StandardCharsets.UTF_8);
String error = IOUtils.toString(process.getErrorStream(), StandardCharsets.UTF_8);
int exitValue = process.waitFor();
logger.info("command: {}, result: {}, error: {}, exitValue: {}", command, result, error, exitValue);
if (exitValue == 0) {
return ReturnT.SUCCESS;
} else {
return new ReturnT<String>(ReturnT.FAIL_CODE, "command execute failed, exitValue=" + exitValue);
}
}
}
五、在调度中心配置执行器和任务
1. 配置执行器
- 登录调度中心(http://localhost:8080/xxl-job-admin)
- 点击左侧菜单「执行器管理」->「新增」
- 填写执行器信息:
- 执行器AppName:xxl-job-executor-sample(与SpringBoot配置中的appname保持一致)
- 执行器名称:示例执行器
- 注册方式:自动注册
- 机器地址:留空(自动注册时不需要填写)
2. 配置任务
- 点击左侧菜单「任务管理」->「新增」
- 填写任务信息:
- 执行器:选择刚刚创建的「示例执行器」
- 任务描述:Demo任务
- 调度类型:CRON
- CRON:0/30 * * * * ?(每30秒执行一次)
- 运行模式:BEAN
- JobHandler:demoJobHandler(与@XxlJob注解中的值保持一致)
- 阻塞处理策略:单机串行
- 任务参数:可填写自定义参数
3. 启动任务
- 在任务管理列表中找到刚刚创建的任务
- 点击「操作」列的「启动」按钮
- 查看任务执行日志,确认任务正常运行
六、XXL-JOB 高级功能
1. 任务参数传递
@XxlJob("demoJobHandler")
public ReturnT<String> demoJobHandler(String param) throws Exception {
logger.info("接收到的任务参数: {}", param);
// 业务逻辑处理
return ReturnT.SUCCESS;
}
2. 任务失败重试
调度中心配置中,可以设置任务失败后的重试次数和重试间隔。
3. 分片任务
适用于大数据量的任务处理场景,将一个大任务分成多个小任务在不同机器上并行执行:
@XxlJob("shardingJobHandler")
public ReturnT<String> shardingJobHandler(String param) throws Exception {
// 获取分片参数
int shardIndex = XxlJobHelper.getShardIndex(); // 当前分片索引
int shardTotal = XxlJobHelper.getShardTotal(); // 总分片数
logger.info("分片参数:当前分片 = {}, 总分片 = {}", shardIndex, shardTotal);
// 根据分片索引处理对应的数据范围
// 例如:处理数据库中 id % shardTotal == shardIndex 的数据
return ReturnT.SUCCESS;
}
4. 任务依赖
可以配置任务的前置依赖,确保任务按照指定顺序执行。
七、常见问题及解决方案
1. 执行器注册失败
- 检查调度中心地址是否正确
- 检查 accessToken 是否与调度中心一致
- 检查执行器端口是否被占用
- 查看日志中的具体错误信息
2. 任务执行失败
- 检查任务处理器中的业务逻辑
- 查看执行器日志中的错误信息
- 确认任务参数格式正确
3. 任务阻塞
- 合理设置任务的执行时间
- 选择合适的阻塞处理策略
- 对于长时间运行的任务,考虑拆分为多个小任务
八、最佳实践
- 合理设置任务调度频率:避免过于频繁的任务执行导致系统负载过高
- 任务幂等性设计:确保任务重复执行不会产生副作用
- 任务超时控制:设置合理的任务超时时间,避免任务无限执行
- 资源隔离:不同类型的任务尽量部署在不同的执行器上
- 监控和报警:配置任务执行失败的报警机制
- 日志管理:定期清理任务日志,避免磁盘空间不足
九、完整的项目结构
src/
├── main/
│ ├── java/com/example/
│ │ ├── config/
│ │ │ └── XxlJobConfig.java # XXL-JOB 配置类
│ │ ├── jobhandler/
│ │ │ └── SampleXxlJob.java # 任务处理器
│ │ └── XxlJobExecutorApplication.java # 应用入口
│ └── resources/
│ ├── application.yml # 配置文件
│ └── logback.xml # 日志配置
└── pom.xml # Maven 配置
以上就是 SpringBoot 整合 XXL-JOB 的完整实现方案。通过这种方式,您可以轻松地在 SpringBoot 项目中实现分布式任务调度,提高系统的可靠性和可维护性。