xxl-job - xxl-job-admin 启动流程
xxl-job-admin启动流程
xxl-job-admin
XxlJobAdminConfig.afterPropertiesSet()
+ XxlJobScheduler.init()
+ initI18n()
+ JobTriggerPoolHelper.toStart(): 初始化快慢线程池
+ 启动 fastTriggerPool 线程
+ 启动 slowTriggerPool 线程
+ JobRegistryHelper.getInstance().start()
+ 启动registryOrRemoveThreadPool线程
+ 启动 :主要是清理过期注册的执行器
+ 删除过期注册地址:到数据库拉取最新注册的xxl-job-executor的注册地址: 更新时间< now-3*30【更新时间小于3个心跳时间之前】
+ 刷新执行器注册时间: 到数据库拉取最新注册的xxl-job-executor的注册地址: 更新时间> now-3*30【更新时间在3个心跳之内】
+ JobFailMonitorHelper.getInstance().start()
+ JobCompleteHelper.getInstance().start()
+ JobLogReportHelper.getInstance().start()
+ 启动 logrThread 线程
+ 刷新3天之内调度数据,从 xxl_job_log中统计失败,成功,进行中的数据 ,即首页的拆线图
+ 如果开启日志清除,根据设置的过期天数清除日志
+ 处理完sleep一分钟
+ JobScheduleHelper.getInstance().start()
+ 启动 scheduleThread 线程
+ sleep 5秒内
+ 计算预读任务数量 preReadCount
+ 手动开启 mysql 事务 查询`select * from xxl_job_lock where lock_name = 'schedule_lock' for update`
+ 从数据库预查询出 record < now+ PRE_READ_MS【默认5秒】 limit preReadCount
+ 如果当前时间超出 触发时间+ PRE_READ_MS: 说明任务已经过了触发时间
+ 查找 任务错过策略,如果是错过再执行一次,那就立即触发一次任务
+ 刷新任务一次触发时间
+ 如果当前时间 大于 触发时间
+ 直接触发任务执行
+ 计算刷新任务下次触发时间
+ 如果下次触发的时间还在这5秒内,再次把任务提交给 ringData,期待与【其他】一样的操作
+ 其他
+ 计算任务触发时间在 ringData 的哪个槽
+ 将jobId放入 ringData
+ 计算刷新任务下次触发时间
+ 批量更新任务下次触发时间
+ 提交事务
+ 启动 ringThread 线程
+ 从 ringData 中向前取2个槽的jobId列表 `List<Integer> tmpData = ringData.remove( (nowSecond+60-i)%60 )`
+ 触发任务调度
+ 问题: 如果系统突然崩溃,内存中的任务列表怎么处理?
+ 在 stop() 方法中, ringThread 执行interrupt后,线程会一直 join 等待,`ringThread.join()`
+ JobTriggerPoolHelper.trigger() 触发任务执行
+ 根据 jobId 从 jobTimeoutCountMap 取出正在执行的job触发数量(相同任务,不同触发时间)
+ 如果job正在执行数量>10,则使用慢线程池,不然使用快线程池
+ 执行任务调度
+ 根据 JobId查询jobInfo
+ 查询 job-executor 注册列表
+ 如果是分片广播任务
+ 给每个执行器job-executor都下发相同的任务
+ 并且将执行器id和分片总数一起下发给执行器
+ 执行器可获取自己的 id,根据 id 去判断是否要执行该任务
+ 如果不是
+ 根据路由策略先出一个执行器地址
+ 构造 TriggerParam 参数
+ 创建调度日志 XxlJobLog
+ 通过 ExecutorBizClient 执行器 job-excutor 发送执行job请求
+ 更新任务调度日志 XxlJobLog