XXL-JOB:调度中心、执行器与任务处理
整理 XXL-JOB 组件关系、任务处理器及接入配置的核心知识。
阅读设置
这是一份关于 XXL-JOB 分布式任务调度平台 的核心复习笔记。结合你提供的 Demo 代码,这份笔记涵盖了架构、配置、开发及高级用法。
1. 核心架构与概念
XXL-JOB 采用 调度中心(Admin) 与 执行器(Executor) 分离的架构。
| 组件 | 角色 | 职责 | 关键技术 |
|---|---|---|---|
| 调度中心 (Admin) | 大脑 | 管理任务信息、发送调度请求、监控执行状态、查看日志。 | Spring Boot + MyBatis + Quartz (仅用于触发时间点) |
| 执行器 (Executor) | 手脚 | 接收调度请求、执行业务逻辑、返回执行结果。 | Netty (RPC通讯)、Spring Bean |
| 数据库 | 记忆 | 存储任务配置、执行日志、注册机器列表。 | MySQL (QRTZ_表 + XXL_JOB_表) |
核心流程
- 注册:执行器启动后,向 Admin 发送心跳,注册 IP:Port。
- 调度:Admin 根据 Cron 表达式,到点通过 Netty RPC 调用执行器。
- 执行:执行器找到对应的
@XxlJob方法执行。 - 回调:执行器将结果(成功/失败/日志ID)异步汇报给 Admin。
2. 执行器配置 (application.yml)
这是整合 XXL-JOB 的第一步,必须准确配置。
xxl:
job:
access-token: default_token # ⭐ 安全令牌,Admin 和 Executor 必须一致
admin:
address: http://127.0.0.1:18080/xxl-job-admin # Admin 地址
executor:
app-name: my-executor # ⭐ 执行器标识,Admin 后台配置需与此一致
port: 9999 # ⭐ Netty 端口,不能与 Web 端口冲突
log-path: ./logs/xxl-job # 本地日志路径
log-retention-days: 30 # 日志保留天数
关键点:
- App-Name:是执行器的分组依据。同一个微服务模块通常共用一个 App-Name。
- Port:单机多实例部署时,每个实例的 Port 必须不同。
3. 代码开发规范
A. 定义任务 Handler
在 Spring Bean 中使用 @XxlJob 注解。
@Component
public class MyJobHandler {
@XxlJob("demoTask") // ⭐ JobHandler 名称,Admin 配置时必须填这个
public void execute(String param) throws Exception {
XxlJobHelper.log("XXL-JOB, Hello World.");
// 业务逻辑...
if (fail) {
XxlJobHelper.handleFail("执行失败原因");
} else {
XxlJobHelper.handleSuccess();
}
}
}
B. 常用 API (XxlJobHelper)
log(): 打印日志,可在 Admin 后台实时查看。handleSuccess(): 标记任务成功。handleFail(msg): 标记任务失败。getJobParam(): 获取 Admin 下发的参数。
4. 高级特性与路由策略
在 Admin 后台配置任务时,有几个关键选项决定了任务的执行行为:
A. 路由策略 (当执行器集群部署时)
| 策略 | 含义 | 场景 |
|---|---|---|
| 第一个 | 固定选择第一台机器 | 简单测试 |
| 轮询 (ROUND) | 依次分配给每台机器 | 负载均衡,最常用 |
| 故障转移 (FAILOVER) | 心跳检测,坏了换下一台 | 高可用要求高 |
| 忙碌转移 (BUSYOVER) | 检测线程池,忙则换下一台 | 防止单点过载 |
| 分片广播 (SHARDING) | 所有机器都执行,携带分片参数 | 海量数据处理 |
B. 阻塞处理策略 (当上一次任务还没跑完,下一次触发时间到了)
| 策略 | 含义 |
|---|---|
| 单机串行 (SERIAL_EXECUTION) | 排队等待,上一个跑完再跑下一个。推荐 |
| 丢弃后续调度 (DISCARD_LATER) | 忽略本次触发 |
| 覆盖之前调度 (COVER_EARLY) | 中断上一个,立即开始新的 |
C. 分片广播 (Sharding) - 大数据利器
- 原理:假设集群有 3 台机器,任务分片总数设为 3。
- 机器 0 收到:
index=0, total=3-> 处理 ID % 3 == 0 的数据 - 机器 1 收到:
index=1, total=3-> 处理 ID % 3 == 1 的数据 - 机器 2 收到:
index=2, total=3-> 处理 ID % 3 == 2 的数据
- 机器 0 收到:
- 代码获取:
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
5. 动态管理任务 (API 方式)
如 ManualOperateController.java 所示,可以通过 HTTP 请求 Admin 接口实现业务驱动的任务管理。
- 新增任务:
POST /jobinfo/add- 关键字段:
executorHandler(对应注解名),jobCron,glueType(BEAN)。
- 关键字段:
- 手动触发:
POST /jobinfo/trigger- 场景:测试、补跑数据。
- 启停/删除:
/start,/stop,/remove
⚠️** 注意**:生产环境建议封装 Service 层,并加上严格的权限校验,不要直接暴露这些接口。
6. 常见问题与避坑指南
- 任务不执行?
- 检查 Admin 和 Executor 的
access-token是否一致。 - 检查 Executor 是否在 Admin 后台显示为“在线”。
- 检查防火墙是否放行了 Executor 的
port(9999)。
- 检查 Admin 和 Executor 的
- 日志看不到?
- 检查
log-path目录是否有读写权限。 - 检查 Admin 是否能访问 Executor 的 IP(如果是 Docker/K8s 环境,注意 IP 映射问题)。
- 检查
- 重复执行?
- 检查路由策略是否误选了“分片广播”或“故障转移”导致的多机执行。
- 确保业务逻辑本身具有幂等性。
- Cron 表达式写错?
- XXL-JOB 后台有 Cron 生成工具,建议先用工具生成测试。
7. 总结:XXL-JOB vs Quartz
| 维度 | Quartz | XXL-JOB |
|---|---|---|
| 管理界面 | 无 (需自研) | 自带强大 Web 后台 |
| 分布式支持 | 弱 (依赖 DB 锁) | 强 (原生支持集群、分片) |
| 动态性 | 一般 | 极强 (在线增删改查、日志查看) |
| 上手难度 | 中 | 低 (开箱即用) |
| 适用场景 | 单体、简单定时任务 | 微服务、分布式、海量任务 |
一句话记忆:
Quartz 是库,XXL-JOB 是平台。 如果项目上了微服务或者需要频繁运维定时任务,无脑选 XXL-JOB。
避免版本混用
不要把 Quartz 的 QRTZ 表和某一历史版本设计当作所有 XXL-JOB 的实现。现代 @XxlJob 方法通常无参数,通过 XxlJobHelper.getJobParam() 获取任务参数;具体签名和返回方式以目标版本为准。属性名也要与实际执行器配置类一致。