Xxl-Job技术分享
- 什么是Xxl-Job
XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。
github地址:https://github.com/xuxueli/xxl-job
- Xxl-Job需要的环境
- Maven3+
- Jdk1.8+
- Mysql5.7+
- Xxl-Job的组成部分
XXL-JOB主要分为”调度中心”和”执行器”,其中调度中心是一个注册中心,每一个执行器启动后都会自动注册到调度中心,调度中心可通过可视化页面,对执行器进行编辑,另外XXL-JOB还包括日志模块,用户模块,任务管理,和运行报表(统计功能)
- 调度模块(调度中心):
负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块;
支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,GLUE开发和任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover。 - 执行模块(执行器):
负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效;
接收“调度中心”的执行请求、终止请求和日志请求等。
调度中心访问地址:http://localhost:8080/xxl-job-admin (该地址执行器将会使用到,作为回调地址)
默认登录账号 “admin/123456”,
- 快速入门
1下载源码并启动调度中心
github地址:https://github.com/xuxueli/xxl-job
Admin模块为调度中心
Core 模块为工具类
Xxl-job-executor-samples 模块为官方demo
Admin模块启动前需要执行doc/db/tables_xxl_job.sql脚本,在数据库中创建以下几张表
2引入jar包
<!-- xxl-job-core -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.1</version>
</dependency>
3创建自己的执行器
3.1执行器配置文件
### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 执行器通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=
### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
xxl.job.executor.appname=xxl-job-executor-sample
### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
xxl.job.executor.address=
### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
xxl.job.executor.ip=
### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
xxl.job.executor.port=9999
### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
xxl.job.executor.logretentiondays=30
3.2执行器通过配置类初始化XxlJobSpringExecutor
3.3创建自己的任务处理逻辑
3.4初始化流程以及自动注册
XxlJobSpringExecutor 继承了 XxlJobExecutor,实现了 ApplicationContextAware, DisposableBean,SmartInitializingSingleton
可以看出 ,其实整个逻辑是在类XxlJobExecutor 里面,类XxlJobSpringExecutor 是为了匹配Spring 框架而做的改造
实现ApplicationContextAware 是为了获取上下文
实现DisposableBean是为了重写destroy 方法,用于释放一些资源
实现SmartInitializingSingleton,这个比较关键,也是重点,就是在Bean 创建的生命周期里面,单例 bean 都初始化完成以后,找出带有注解的 job进行注册等一系列操作()
GlueFactory主要处理GLUE(Java)类型作业,对GLUE(Java)类型作业源码进行编译、创建实例进行调用,可以支持spring依赖注入,如源码中支持@Autowired、@Resource、@Qualifier等。
接下来调用父类start() 方法,上面说过XxlJobExecutor 里面的才是核心逻辑
初始化log路径,没有给定,默认是 /data/applogs/xxl-job/jobhandler
初始化invoker, admin-client
这里就是给定的 admin server 端地址,一个或者多个,封装成AdminBizClient 对象
放在adminBizList list里面,以便后面的回调,注册,移除等操作
initAdminBizList(adminAddresses, accessToken);
initAdminBizList方法遍历调度器的地址,即admin服务的地址,adminAddresses地址是以逗号分隔的,每一个admin地址就创建admin客户端AdminBizClient,AdminBizClient是执行器与admin服务通信的客户端,是通过http进行通信的,通过AdminBizClient执行器就可以注册执行器、删除执行器以及将定时任务的结果回调给admin保存起来。最后将创建好的AdminBizClient保存到adminBizList中。AdminBizClient实现了AdminBiz接口
AdminBiz接口有三个方法,registry方法用来注册执行器的,registryRemove方法用来删除执行器的,callback方法是将定时任务的执行的结果回调保存到数据库中。AdminBizClient是admin客户端,AdminBizImpl是admin服务端,AdminBizClient的三个方法通过http请求转发给AdminBizImpl对应的是三个方法。
初始化 日志 清理线程,定时清理
JobLogFileCleanThread.getInstance().start(logRetentionDays);
初始化回调线程
TriggerCallbackThread.getInstance().start();
初始化 executor-server
重点来了
initEmbedServer(address, ip, port, appname, accessToken);
initEmbedServer 方法主要逻辑是 ,获取IP 和port , 调用EmbedServer.start
其中如我们没有在配置文件指定端口,默认是9999,如果9999被占用,默认加1,比如10000,另外prot大于65535的话,会做-1的操作,止到获取可用的端口
接下来看看
embedServer.start(address, port, appname, accessToken);
使用netty初始化启动了一个http server,主要用于接收admin模块向执行器发送指令,比如下发执行作业指令、kill作业指令,主要处理逻辑封装在EmbedHttpServerHandler中;
startRegistry(appname, address)启动客户端执行器定时向admin模块注册线程,逻辑代码在ExecutorRegistryThread#start方法中;
向注册中心发起请求,请求成功话,会在表中插入一条记录,存在的话就修改,不存在就新增,
同时表xxl_job_registry会记录,启动的执行器
1、客户端利用adminBiz.registry(registryParam)定时周期向admin模块发送注册信息;
2、admin模块接收到客户端注册信息后,插入|更新xxl_job_registry表的update_time字段时间值;
- admin模块在JobRegistryMonitorHelper中启动线程定时扫描xxl_job_registry表,将超时移除,并将在线实例集合拼接在一起更新到执行器地址为自动注册的执行器address_list字段信息中。
3.5调度中心的执行流程
当我们再页面上点击执行时
这里根据一定规则将触发任务从两个线程池中选取一个进行投递
fastTriggerPool:默认投递线程池
slowTriggerPool:慢作业投递到该线程池
慢作业定义:投递超过500ms,且累计一分钟超过10次(每分钟重置缓存重新计算),则该作业就是慢作业,后续执行时使用slowTriggerPool
接下来进入XxlJobTrigger.trigger方法
主要处理一些参数,主要的方法是 processTrigger(group, jobInfo, finalFailRetryCount, triggerType, i, group.getRegistryList().size());
前两行对应不用的策略
路由策略和阻塞处理策略
runExecutor()才是发送http请求的方法
根address获取对应的执行器代理ExecutorBiz,然后调用其run方法将作业下发到执行器端运行。上节分析过执行器启动时使用netty初始化一个http server的web容器,所以,这里的下发逻辑比较简单,就是调用http接口XxlJobRemotingUtil.postBody(addressUrl + "run", accessToken, timeout, triggerParam, String.class);。
五.案列分享
分布式任务调度平台XXL-JOB 官方文档