Xxl Job
前言
在此之前对于xxl-job仅仅限于使用级别,对其底层实现一无所知,闲来无事,翻翻源码研究一下
准备
- xxl-job-V2.3.0版本源码下载;github源码仓库 gitee源码仓库
- 阅读官方文档
- 根据官方文档、启动代码
工程目录结构分析
| |
xxl-job-admin模块是调度中心,统一管理任务调度平台上调度任务,负责触发调度执行,并且提供任务管理平台。
xxl-job-core模块是公共的依赖,供调度中心以及调度任务依赖。
xxl-job-executor-samples是执行器案例,有两个执行器案例,xxl-job-executor-sample-springboot是spring版本。xxl-job-executor-sample-frameless是普通的版本,直接通过main方法启动。
调度中心启动流程分析
在启动xxl-job,首先应该启动xxl-job-admin,然后启动执行案例的其中一个。xxl-job-admin是springboot项目,可以直接启动,具体启动方法直接参考官方的文档,非常的详细。今天要将的内容就是xxl-job-admin的启动流程分析。
在启动xxl-job-admin的过程中,XxlJobAdminConfig是配置类,在afterPropertiesSet方法中会创建调度器以及对调度器进行初始化。
| |
xxlJobScheduler.init()方法主要做了如下几件事
- 国际化初始化 initI18n()
- 触发器线程池创建 JobTriggerPoolHelper.toStart();
- 注册监控器启动 JobRegistryHelper.getInstance().start();
- 失败监控器启动 JobFailMonitorHelper.getInstance().start();
- 丢失监控器启动 JobCompleteHelper.getInstance().start();
- 日志任务启动 JobLogReportHelper.getInstance().start();
- 调度启动 JobScheduleHelper.getInstance().start();
| |
触发器线程池创建
JobTriggerPoolHelper.toStart()最终调用JobTriggerPoolHelper.start()
| |
fastTriggerPool为快速线程池、slowTriggerPool为慢速线程池,都是采用阻塞队列LinkedBlockingQueue,快速线程池的阻塞队列大小为1000,慢速线程池的阻塞队列大小为2000。快速线程池、慢速线程池在什么时候被用来调度任务呢?默认是用快速调度器调度任务的,当缓存中等待被调度的同一个任务的数量大于10的时候,就用慢速调度器调度任务。
注册监控器启动
JobRegistryHelper.getInstance().start()
| |
- JobRegistryHelper的start创建了一个调度任务注册线程池registryOrRemoveThreadPool以及注册监控器线程registryMonitorThread,调度任务注册线程池用来执行调度任务的注册,注册监控器线程用来监控执行器的机器是否下线。然后将registryMonitorThread设置为守护线程,最后启动registryMonitorThread线程,开始监控执行器的机器。
- registryMonitorThread线程的run方法的代码逻辑参考上述代码片段的registryMonitorThread=new 中的run方法:run()方法一直执行,直到服务停止.
- 第一将已经下线的执行器的记录从数据库中删除,
- 第二将还在线的执行器机器记录重新设置执行器地址以及更新执行器的时间,然后更新数据库的记录。
- 怎么判定执行器已经下线了:如果数据库中的update_time字段小于当前时间减去死亡期限,那么说明已经执行器在死亡期限没有进行更新时间,就判定已经下线了。执行器在启动的时候,会启动一个执行器线程不断的执行注册任务,执行器任务会更新update_time字段。
失败监控器启动
JobFailMonitorHelper.getInstance().start()
| |
- 1 创建了一个名字为monitorThread的线程,并设为守护线程,然后启动这个线程。run方法一直运行,直到线程停止。
- 2 run方法的首先从数据库中获取失败的调度任务日志列表(每次最多一千条)
- 3 遍历失败的调度任务日志列表:
- 3.1 将失败的调度任务日志进行锁定。
- 3.2 如果调度任务的失败重试次数大于0,可重试,触发任务执行(JobTriggerPoolHelper.trigger()),更新任务日志信息(重试次数减一)。
- 3.3 当邮件不为空时,触发告警信息,最后将锁定的日志状态更新为告警状态。
丢失(掉线)监控器启动
JobCompleteHelper.getInstance().start();代码组织同上略去
- 启动回调线程池callbackThreadPool和丢失(掉线)监控线程monitorThread
- 丢失(掉线)监控线程monitorThread任务结果丢失处理:调度记录停留在 “运行中” 状态超过10min,且对应执行器心跳注册失败不在线,则将本地调度主动标记失败;
日志任务启动
JobLogReportHelper.getInstance().start() 代码组织同上略去
1、统计当前时间前三天的触发任务的数量、运行中的任务的数量、成功的任务数量、任务失败的数量,然后保存在数据库中。
2、根据配置的保存日志的过期时间,将已经过期的日志从数据库中查出来,然后清理过期的日志。日志任务启动是创意了一个线程,然后一直在后台运行。
调度启动 JobScheduleHelper.getInstance().start();
| |