JOURNAL / WORDS & IDEAS

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_表)

核心流程

  1. 注册:执行器启动后,向 Admin 发送心跳,注册 IP:Port。
  2. 调度:Admin 根据 Cron 表达式,到点通过 Netty RPC 调用执行器。
  3. 执行:执行器找到对应的 @XxlJob 方法执行。
  4. 回调:执行器将结果(成功/失败/日志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 的数据
  • 代码获取:
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. 常见问题与避坑指南

  1. 任务不执行?
    • 检查 Admin 和 Executor 的 access-token 是否一致。
    • 检查 Executor 是否在 Admin 后台显示为“在线”。
    • 检查防火墙是否放行了 Executor 的 port (9999)。
  2. 日志看不到?
    • 检查 log-path 目录是否有读写权限。
    • 检查 Admin 是否能访问 Executor 的 IP(如果是 Docker/K8s 环境,注意 IP 映射问题)。
  3. 重复执行?
    • 检查路由策略是否误选了“分片广播”或“故障转移”导致的多机执行。
    • 确保业务逻辑本身具有幂等性。
  4. 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() 获取任务参数;具体签名和返回方式以目标版本为准。属性名也要与实际执行器配置类一致。