分布式任务调度平台 xxl-job
分布式任务调度平台
1、概念
官方地址中文版:http://www.xuxueli.com/xxl-job
什么是xxl-job?
XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。
特性:学习简单、轻量级、易扩展。
定时任务框架quartz、elastic-job和xxl-job分析:
https://blog.csdn.net/LWS826528071/article/details/94394249
一文读懂分布式任务调度平台XXL-JOB:
https://blog.csdn.net/HUXU981598436/article/details/102695890
发展过程:
- 2015年中,在github上创建XXL-JOB项目仓库。
- 2015-11月,XXL-JOB终于RELEASE了第一个大版本V1.0。
- 2022-04-14 发行了 2.3版本
1.1、源码目录介绍
版本:2.1.3-SHAPSHOT
- /doc :文档资料
- /db :“调度数据库”建表脚本
- /xxl-job-admin :调度中心,项目源码
- /xxl-job-core :公共Jar依赖
- /xxl-job-executor-samples :执行器,Sample示例项目
1.2 、数据库表说明
- 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:系统用户表;
1.3、 架构设计
1.3.1 设计思想
将调度行为抽象形成“调度中心”公共平台,而平台自身并不承担业务逻辑,“调度中心”负责发起调度请求。
将任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑。
因此,“调度”和“任务”两部分可以相互解耦,提高系统整体稳定性和扩展性;
1.3.2 系统组成
- 调度模块(调度中心):
负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块;
支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,GLUE开发和任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover。 - 执行模块(执行器):
负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效;
接收“调度中心”的执行请求、终止请求和日志请求等。
1.3.3 架构图

2、快速入门
下载项目源码并解压
2.1 、初始化数据库
/xxl-job/doc/db/tables_xxl_job.sql
2.2、启动调度中心
1、导入项目到IDEA.
2、打开xxl-job-admin,检查配置
3、启动项目,默认地址是
- http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址)
- 默认登录账号 "admin/123456", 登录后运行界面如下图所示。

4、到了这步调度中心就启动成功了。
调度中心支持集群部署,提升调度系统容灾和可用性。
调度中心集群部署时,几点要求和建议:
- DB配置保持一致;
- 集群机器时钟保持一致(单机集群忽视);
- 建议:推荐通过nginx为调度中心集群做负载均衡,分配域名。调度中心访问、执行器回调配置、调用API服务等操作均通过该域名进行。
2.3、启动执行器
1、打开xxl-job-executor-samples下的xxl-job-executor-sample-springboot,检查配置
2、启动项目
3、到了这步执行器就启动成功了。
3、任务详解
配置属性详细说明:
基础配置:
- 执行器:任务的绑定的执行器,任务触发调度时将会自动发现注册成功的执行器, 实现任务自动发现功能; 另一方面也可以方便的进行任务分组。每个任务必须绑定一个执行器, 可在 "执行器管理" 进行设置;
- 任务描述:任务的描述信息,便于任务管理;
- 负责人:任务的负责人;
- 报警邮件:任务调度失败时邮件通知的邮箱地址,支持配置多邮箱地址,配置多个邮箱地址时用逗号分隔;
触发配置:
- 调度类型:
无:该类型不会主动触发调度;
CRON:该类型将会通过CRON,触发任务调度;
固定速度:该类型将会以固定速度,触发任务调度;按照固定的间隔时间,周期性触发;
固定延迟:该类型将会以固定延迟,触发任务调度;按照固定的延迟时间,从上次调度结束后开始计算延迟时间,到达延迟时间后触发下次调度;
- CRON:触发任务执行的Cron表达式;
- 固定速度:固件速度的时间间隔,单位为秒;
- 固定延迟:固件延迟的时间间隔,单位为秒;
任务配置:
- 运行模式:
BEAN模式:任务以JobHandler方式维护在执行器端;需要结合 "JobHandler" 属性匹配执行器中任务;
GLUE模式(Java):任务以源码方式维护在调度中心;该模式的任务实际上是一段继承自IJobHandler的Java类代码并 "groovy" 源码方式维护,它在执行器项目中运行,可使用@Resource/@Autowire注入执行器里中的其他服务;
GLUE模式(Shell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "shell" 脚本;
GLUE模式(Python):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "python" 脚本;
GLUE模式(PHP):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "php" 脚本;
GLUE模式(NodeJS):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "nodejs" 脚本;
GLUE模式(PowerShell):任务以源码方式维护在调度中心;该模式的任务实际上是一段 "PowerShell" 脚本;
- JobHandler:运行模式为 "BEAN模式" 时生效,对应执行器中新开发的JobHandler类“@JobHandler”注解自定义的value值;
- 执行参数:任务执行所需的参数;
高级配置:
- 路由策略:当执行器集群部署时,提供丰富的路由策略,包括;
FIRST(第一个):固定选择第一个机器;
LAST(最后一个):固定选择最后一个机器;
ROUND(轮询):;
RANDOM(随机):随机选择在线的机器;
CONSISTENT_HASH(一致性HASH):每个任务按照Hash算法固定选择某一台机器,且所有任务均匀散列在不同机器上。
LEAST_FREQUENTLY_USED(最不经常使用):使用频率最低的机器优先被选举;
LEAST_RECENTLY_USED(最近最久未使用):最久未使用的机器优先被选举;
FAILOVER(故障转移):按照顺序依次进行心跳检测,第一个心跳检测成功的机器选定为目标执行器并发起调度;
BUSYOVER(忙碌转移):按照顺序依次进行空闲检测,第一个空闲检测成功的机器选定为目标执行器并发起调度;
SHARDING_BROADCAST(分片广播):广播触发对应集群中所有机器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务;
- 子任务:每个任务都拥有一个唯一的任务ID(任务ID可以从任务列表获取),当本任务执行结束并且执行成功时,将会触发子任务ID所对应的任务的一次主动调度。
- 调度过期策略:
- 忽略:调度过期后,忽略过期的任务,从当前时间开始重新计算下次触发时间;
- 立即执行一次:调度过期后,立即执行一次,并从当前时间开始重新计算下次触发时间;
- 阻塞处理策略:调度过于密集执行器来不及处理时的处理策略;
单机串行(默认):调度请求进入单机执行器后,调度请求进入FIFO队列并以串行方式运行;
丢弃后续调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,本次请求将会被丢弃并标记为失败;
覆盖之前调度:调度请求进入单机执行器后,发现执行器存在运行的调度任务,将会终止运行中的调度任务并清空队列,然后运行本地调度任务;
- 任务超时时间:支持自定义任务超时时间,任务运行超时将会主动中断任务;
- 失败重试次数;支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;
Cron表达式

3.1、BEAN模式
BEAN模式两种形式:
- 类形式
- 基于类的开发方式,每个任务对应一个Java类
- 优点:
- 不限制项目环境,兼容性好。
- 缺点:
- 每个任务对应一个Java类,造成类的浪费;
- 不支持自动扫描任务并注入到执行器容器,需要手动注入。
- 方法形式
- 基于方法的开发方式,每个任务对应一个方法。
- 优点:
- 每个任务只需要开发一个方法,并添加"@XxlJob"注解即可,更加方便、快速。
- 支持自动扫描任务并注入到执行器容器。
- 缺点:
- 要求Spring容器环境;
主要讲解方法形式
1、创建Job方法
// 创建Job,可参考Sample示例执行器中的 "com.xxl.job.executor.service.jobhandler.SampleXxlJob"
@XxlJob("demoJob")
public void demoJob() throws Exception {
XxlJobHelper.log("测试XXL-JOB, 方法形式======》");
}
2、添加调度任务,JobHandler属性填写任务注解@XxlJob中定义的值;

3、执行任务,查询日志

3.2、GLUE模式(Java)
任务以源码方式维护在调度中心,支持通过Web IDE在线更新,实时编译和生效,因此不需要指定JobHandler。
1、在调试中心里创建一个GLUE模式(Java)任务。

2、进入GLUE编辑器开发界面

3、执行任务,查看日志

3.3、其它运行模式
- GLUE模式(Shell),支持 "Shell" 脚本任务;
- GLUE模式(Python),支持 "Python" 脚本任务;
- GLUE模式(PHP),支持 "PHP" 脚本任务;
- GLUE模式(NodeJS),支持 "NodeJS" 脚本任务;
- GLUE模式(Powershell),支持 "PowerShell" 脚本任务;
4、执行器管理
执行器实际上是一个内嵌的Server

- AppName:唯一标示,执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器, 供任务调度时使用;
- 名称:提高执行器的可读性
- 自动注册:执行器自动进行执行器注册,调度中心通过底层注册表可以动态发现执行器机器地址;
- 手动录入:人工手动录入执行器的地址信息,多地址逗号分隔,供调度中心使用;
5、用户管理
进入 "用户管理" 界面,可查看和管理用户信息;
目前用户分为两种角色:
- 管理员:拥有全量权限,支持在线管理用户信息,为用户分配权限,权限分配粒度为执行器;
- 普通用户:仅拥有被分配权限的执行器,及相关任务的操作权限;

6、在项目中使用
6.1、添加基础配置
1、添加依赖
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.1-SNAPSHOT</version>
</dependency>
2、添加配置信息
### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 执行器通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=
### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
xxl.job.executor.appname=xxl-job-my-demo
## 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
xxl.job.executor.address=
### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
xxl.job.executor.ip=
### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
xxl.job.executor.port=9998
### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
xxl.job.executor.logretentiondays=30
3、添加xxlJob配置类
XxlJobConfig.java
package com.heyuht.hospital.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;
/**
* xxl-job config
*
* @author xuxueli 2017-04-28
*/
@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.address}")
private String address;
@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.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
}
6.2、 创建测试用例
1、添加job文件夹,方便管理
2、创建XxlJobDemo.java
@Component
@Slf4j
public class XxlJobDemo {
@Autowired
private ISysUserService sysUserService;
/**
* 需求,每过一分钟,查询用户总数
*/
@XxlJob("countUser")
public void demoJob(){
XxlJobHelper.log("XXL-JOB,测试任务开始执行======》");
int count = sysUserService.count();
XxlJobHelper.log("XXL-JOB,测试任务执行结束======《,当前人数:{}",count);
}
}
3、添加执行器

4、启动项目,查询控制台日志

查询执行器注册地址。

5、添加任务

6、执行任务,查看日志。

7、源码分析
7.1、启动调度中心
参考文章:https://www.cnblogs.com/yejg1212/p/14805607.html
1、xxl-job-admin是一个简单的springboot工程,简单翻看源码,可以很快发现XxlJobAdminConfig入口。
@Override
public void afterPropertiesSet() throws Exception {
adminConfig = this;
xxlJobScheduler = new XxlJobScheduler();
xxlJobScheduler.init();
}
2、在XxlJobScheduler.init() 方法中,主要做了如下七件事情:
public void init() throws Exception {
// init i18n
initI18n();
// admin trigger pool start
JobTriggerPoolHelper.toStart();
// admin registry monitor run
JobRegistryHelper.getInstance().start();
// admin fail-monitor run
JobFailMonitorHelper.getInstance().start();
// admin lose-monitor run ( depend on JobTriggerPoolHelper )
JobCompleteHelper.getInstance().start();
// admin log report start
JobLogReportHelper.getInstance().start();
// start-schedule ( depend on JobTriggerPoolHelper )
JobScheduleHelper.getInstance().start();
logger.info(">>>>>>>>> init xxl-job admin success.");
}
2.1、initI18n()
//始化新增任务页面中的阻塞处理策略相关的国际化信息
2.2、JobTriggerPoolHelper.toStart()
// 初始化快慢两个线程池,当任务开始执行的时候使用快线程池。然后当任务执行失败次数达到阈值的时候就会使用慢线程池来执行任务。
// 使执行任务的线程池隔离:调度线程池进行隔离拆分,慢任务自动降级进入"Slow"线程池,避免耗尽调度线程,提高系统稳定性。
2.3、JobRegistryHelper.getInstance().start(); ,注册中心核心类
// 1、开启一个线程池 registryOrRemoveThreadPool ,用来注册或者删除。对象对外提供registry和registryRemove方法
// 2、开启一个线程registryMonitorThread,每sleep 30秒(心跳时间) 移除失活业务服务器记录, 读取存活的xxl_job_registry信息,更新到 xxl_job_group 里面去 。 这个线程被设置为守护线程,通过改变变量标记toStop退出执行
2.4、JobFailMonitorHelper.getInstance().start();
// JobFailMonitorHelper 的作用是开启一个 Daemon 线程主要管理异常调用的任务。如果任务调用失败,它会判断这个任务是否配置了失败重试(默认不重试)。如果配置重试次数大于0就会执行失败重试,如果一直失败最大重试次数就是你配置的重试次数。
2.5、JobCompleteHelper.getInstance().start();
//构造一个 callbackThreadPool 线程池,主要用来更新 xxl_job_log 记录 的执行结果
//构造一个 monitorThread 线程,处理执行超时的。
//找到【调度记录停留在 "运行中" 状态超过10min,且对应执行器心跳注册失败不在线,则将本地调度主动标记失败;】
//更新job_log状态结果
2.6、JobLogReportHelper.getInstance().start();
//1、启动logrThread守护线程,定时扫描xxl_job_log 表
//2、统计执行成功失败的数据,这个其实也是admin里面 执行报表数据的来源
//3、根据配置,清理久远的xxl_job_log历史日志
2.7、JobScheduleHelper.getInstance().start();
// 它的作用就是死循环从xxl_job_info表中取出未来5秒内要执行的任务,进行调度分发。启动了两个守护线程,先来看scheduleThread。
// 首先利用for update语句进行获取任务的资格锁定,再去获取未来5秒内即将要执行的任务。任务的逻辑代码,有三个分支。
// 第一个分支当前任务的触发时间已经超时5秒以上了,不在执行,直接计算下一次触发时间。
// 第二个分支为触发时间已满足,利用JobTriggerPoolHelper这个类进行任务调度,之后判断下一次执行时间如果在5秒内,进行此任务数据的缓存,处理逻辑与第三个分支一样。
// 第三个分支就是对触发时间秒数进行60取模,跟进pushTimeRing方法。
// ringData是以 0 到 59 的整数为key,以jobId集合为value的Map集合。这个集合数据的处理逻辑,就在我们第二个守护线程ringThread中。
//根据当前秒数刻度和前一个刻度进行时间轮的任务获取,之后和上文一样,利用JobTriggerPoolHelper进行任务调度。
7.2、启动执行器
参考文章:https://www.cnblogs.com/yejg1212/p/14794098.html
1、根据示例上,我们能推出``XxlJobConfig`是个核心入口
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appname);
xxlJobSpringExecutor.setAddress(address);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
我们就可以顺着这个XxlJobSpringExecutor,分析下这个xxl-job-core做了些什么。
/**
1、实现ApplicationContextAware,只是为了获取applicationContext对象
2、实现了SmartInitializingSingleton接口,在项目启动的时候,会调到afterSingletonsInstantiated方法。
3、实现了DisposableBean接口,在系统停止的时候,调用destroy方法。
*/
public class XxlJobSpringExecutor extends XxlJobExecutor implements ApplicationContextAware, SmartInitializingSingleton, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(XxlJobSpringExecutor.class);
// start
@Override
public void afterSingletonsInstantiated() {
// init JobHandler Repository
/*initJobHandlerRepository(applicationContext);*/
// init JobHandler Repository (for method)
initJobHandlerMethodRepository(applicationContext);
// refresh GlueFactory
GlueFactory.refreshInstance(1);
// super start
try {
super.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// ....
}
1.1、initJobHandlerMethodRepository(applicationContext),具体实现逻辑如下:
-
通过
applicationContext.getBeanNamesForType获取全部bean -
遍历所有bean,找到有
@XxlJob标记的方法,并判断@XxlJob标记的name值是否有重复,如果重复则报错 -
如果有配置
init和destroy方法,则通过反射找到他们 -
将信息组装成
MethodJobHandler对象,保存到ConcurrentHashMap中registJobHandler(name, new MethodJobHandler(bean, executeMethod, initMethod, destroyMethod));
1.2、GlueFactory.refreshInstance(1),具体实现逻辑如下:
这里初始化了一个SpringGlueFactory
2、启动
这里调用父类XxlJobExecutor的start方法。方法主要执行下面几个大的步骤:
public class XxlJobExecutor {
...
public void start() throws Exception {
// init logpath
XxlJobFileAppender.initLogPath(logPath);
// init invoker, admin-client
initAdminBizList(adminAddresses, accessToken);
// init JobLogFileCleanThread
JobLogFileCleanThread.getInstance().start(logRetentionDays);
// init TriggerCallbackThread
TriggerCallbackThread.getInstance().start();
// init executor-server
initEmbedServer(address, ip, port, appname, accessToken);
}
...
}
2.1、初始化执行器日志路径,默认 /data/applogs/xxl-job/jobhandler,可在配置文件上修改。这个XxlJobFileAppender是个单独写日志文件的工具类。在xxl-job-admin界面上,可以通过界面查看定时任务调度执行的日志。我们在业务代码中,也可以通过XxlJobHelper.log方法,写自己的日志
2.2、根据配置的adminAddresses地址,构造AdminBiz列表(后面注册、调服务端接口等,会需要调到这个地址)
2.3、启动一个daemon线程,每天定期清理调度日志文件(上述1步骤目录下的文件)
2.4、定义一个LinkedBlockingQueue,这个queue里面放job执行结果。然后启动triggerCallbackThread和triggerRetryCallbackThread 两个线程,向job-admin反馈job执行结果。
2.5、构造EmbedServer并启动
//在EmbedServer的start方法中,启动了一个thread,在其内部调了【startRegistry(appname, address);】
//里面还启动了一个registryThread,每30秒注册当前执行器到中心注册
7.3、调度中心添加任务并执行任务
1、调度中心远程调用执行器,当任务需要调度的时候最终都会通过 JobTriggerPoolHelper.trigger()来进行任务调度。
2、通过任务远程调度任务的超时次数选择快/慢线程池来执行任务,接着再调用 XxlJobTrigger.trigger()。
3、它主要的作用是加载任务以及任务所在的执行器。看任务是否需要分片执行。
4、XxlJobTrigger.trigger(),分六部分执行。
4.1、保存任务执行日志信息。
4.2、初始化远程调度的参数。
4.3、根据执行器信息以及路由规则选择合适的执行器地址进行远程调用。
4.4、调用远程执行器XxlJobTrigger.runExecutor()
4.5、收集调度信息
4.6、把调度信息保存到数据库
5、执行器接收请求并运行任务EmbedHttpServerHandler
5.1、首先它根据远程调用的 ExecutorBiz 接口获取到 ExecutorBizImpl 具体实现类,然后调用它的 run 方法。
5.2、如果是 spring bean 模式它会根据配置的 JobHandler 也就是 bean 名称找到对应的任务处理类。如果根据调度中心传过来的 jobId 找不到 JobThread 就通过 XxlJobExecutor新创建一个 JobThread 进行运行,如果能够找到就把需要运行的任务添加到已有 JobThread 的队列中。
5.3、执行 IJobHandler#init 方法
5.4、查看 triggerQueue 队列中是否有任务需要执行
5.5、如果 triggerParam 不为空则继续执行
5.6、创建日志文件,比如:logPath/yyyy-MM-dd/9999.log
5.7、com.xxl.job.core.handler.IJobHandler#execute 执行具体的任务
5.8、调用 TriggerCallbackThread#pushCallBack 把任务执行的日志以及重试日志回写到调度中心
至此整个 xxl-job 如何进行分步式任务调度就完成了。
package com.xxl.job.service.handler;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.IJobHandler;
import com.heyuht.hospital.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
public class DemoGlueJobHandler extends IJobHandler {
@Autowired
private ISysUserService sysUserService;
@Override
public void execute() throws Exception {
XxlJobHelper.log("XXL-JOB,测试任务开始执行======》");
int count = sysUserService.count();
XxlJobHelper.log("XXL-JOB,测试任务执行结束======《,当前人数:{}",count);
}
}

浙公网安备 33010602011771号