针对你的需求,这里整理了一份从 Docker 部署调度中心(Admin)、SpringBoot 执行器开发、控制台配置到分片广播实战的全流程指南。
一、Docker 部署调度中心 (xxl-job-admin)
这是任务调度的"大脑",需要依赖 MySQL 数据库。
1. 数据库初始化
首先在 MySQL 中创建数据库 xxl_job,并执行https://github.com/xuxueli/xxl-job/blob/master/doc/db/tables_xxl_job.sql初始化表结构。
2. Docker 启动 Admin
使用官方镜像 xuxueli/xxl-job-admin:2.4.0 启动容器。注意 :PARAMS 中的数据库连接 IP 需使用 Docker 网络内的 MySQL 容器 IP 或服务名(非 127.0.0.1)。
bash
# 拉取镜像
docker pull xuxueli/xxl-job-admin:2.4.0
# 运行容器(请替换为你实际的 MySQL 连接信息)
# 停止并移除旧容器
docker stop xxl-job-admin1
docker rm xxl-job-admin1
docker run -d \
--name xxl-job-admin \
-p 9080:8080 \
-v /tmp/xxl-job-logs:/data/applogs \
-e PARAMS="--spring.datasource.url=jdbc:mysql://10.10.1.45:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false --spring.datasource.username=root --spring.datasource.password=root" \
xuxueli/xxl-job-admin:2.4.0
启动后访问 http://服务器IP:8080/xxl-job-admin,默认账号 admin/123456。
二、SpringBoot 执行器开发
执行器是承载具体任务逻辑的业务服务。
1. 项目依赖 (pom.xml)
xml
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0</version>
</dependency>
2. 配置文件 (application.yml)
yaml
xxl:
job:
admin:
addresses: http://你的Admin服务器IP:8080/xxl-job-admin # 调度中心地址
accessToken: 你的Token # 若调度中心配置了Token,此处需一致
executor:
appname: xxl-job-executor-demo # 必须与Admin控制台执行器AppName一致
port: 9999 # 执行器端口,需未被占用
logpath: ./logs/xxl-job/jobhandler
logretentiondays: 30
3. 配置类与任务开发
java
@Configuration
public class XxlJobConfig {
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
// ... 其他配置项(accessToken, appname等)
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
XxlJobSpringExecutor executor = new XxlJobSpringExecutor();
executor.setAdminAddresses(adminAddresses);
executor.setAppname(appname);
executor.setPort(port);
return executor;
}
}
@Component
public class DemoJobHandler {
// 1. 简单任务示例
@XxlJob("demoJobHandler")
public void demoJobHandler() throws Exception {
XxlJobHelper.log("简单任务执行成功");
// 你的业务逻辑...
}
// 2. 分片任务示例(详见第四节)
@XxlJob("shardingJobHandler")
public void shardingJobHandler() throws Exception {
int shardIndex = XxlJobHelper.getShardIndex(); // 当前分片号(从0开始)
int shardTotal = XxlJobHelper.getShardTotal(); // 总分片数
// 模拟处理:只有当前分片处理对应数据
if (/* 数据ID % shardTotal == shardIndex */) {
// 处理该分片的数据
}
}
}
三、调度中心控制台配置
1. 配置执行器
路径:执行器管理 -> 新增
- AppName :必须与项目配置文件中的
xxl.job.executor.appname完全一致(如xxl-job-executor-demo)。 - 注册方式 :推荐选择 自动注册(执行器启动后会自动上报地址)。
2. 配置任务
路径:任务管理 -> 新增
- 执行器:选择上一步创建的执行器。
- JobHandler :填写代码中
@XxlJob注解的值(如demoJobHandler)。 - 路由策略 :
- 单机/负载均衡:选择
FIRST(首台)或ROUND(轮询)。 - 分片处理 :必须选择 分片广播(SHARDING_BROADCAST)。
- 单机/负载均衡:选择
- Cron:设置调度表达式。
- 运行模式 :选择
BEAN。
四、分片广播开发详解
分片广播是解决海量数据并行处理的核心方案。其原理是:调度中心一次调度,所有 在线的执行器实例都会同时被触发,每个实例通过 shardIndex 和 shardTotal 区分各自处理的数据区间。
1. 核心代码逻辑
java
@XxlJob("hugeDataJobHandler")
public void hugeDataJobHandler() throws Exception {
int index = XxlJobHelper.getShardIndex();
int total = XxlJobHelper.getShardTotal();
// 1. 查询总数据量(所有分片查询逻辑一致)
int allDataCount = orderMapper.selectCount();
// 2. 计算当前分片负责的数据范围(取模分片法)
List<Order> currentShardData = orderMapper.selectByShard(index, total);
// 3. 处理当前分片的数据
for (Order order : currentShardData) {
// 业务处理...
}
XxlJobHelper.log("分片[{}/{}]处理完成,共处理{}条", index, total, currentShardData.size());
}
2. 数据分片策略(SQL示例)
假设有 1000 条数据,有 2 个执行器(分片总数 total=2):
- 执行器A (index=0):处理 ID % 2 == 0 的数据(偶数ID)。
- 执行器B (index=1):处理 ID % 2 == 1 的数据(奇数ID)。
对应的 MyBatis SQL 映射:
xml
<select id="selectByShard" resultType="Order">
SELECT * FROM order_table
WHERE MOD(id, #{total}) = #{index}
AND status = 'PENDING'
</select>
3. 关键注意事项
- 幂等性:分片任务可能因重试等原因重复执行,业务逻辑需保证幂等。
- 数据倾斜:若使用取模分片,确保数据ID分布均匀,避免某个分片数据量过大。
- 动态扩容:执行器实例数变化(total变化)时,需考虑数据迁移或使用一致性哈希等策略。
五、常见排错清单
- 执行器显示离线 :检查
appname是否与控制台完全一致;检查执行器与 Admin 的网络连通性。 - 任务未触发:检查 Cron 表达式是否正确;确认任务状态为"启动"。
- 分片不生效 :确认路由策略选择了 分片广播 ;代码中是否正确获取了
shardIndex和shardTotal。 - 日志报错 Token 无效 :检查执行器配置的
accessToken是否与 Admin 控制台设置的一致。