分布式调度是高可用的关键,因此特别做研究。以功能/需求/问题为导向,逐个分析实现原理。
目录
- 项目解决了什么核心问题?
- 与其他项目有什么区别和优势
- 功能架构?
核心业务流程
- 执行器注册实现原理?
- 任务注册实现原理?
- 任务执行实现原理?
异常场景处理
- 执行器执行过程中挂了怎么办?
- 调度中心挂了怎么办?
- 怎么保证任务只执行一次?
- 调度中心和执行器怎么连接
- 同时有多个任务,执行器怎么处理
- 一个任务执行时间超时,执行器怎么处理
- 有的任务执行时间很长,有点短,怎么处理
- 怎么注册任务
- 怎么注册执行器
辅助的特性/功能
- 国际化 I18N
- 下阶段迭代特性/功能
- 发展迭代过程中标志性功能
服务接口
登录权限管理
对象:intercepter、PermissionLimit、cookie、token
用户登录/权限管理流程:
- 默认所有请求需要登录,代码上使用intercepter进行校验
- 检查是否cookie是否有token,没有重定向到/toLogin
- 在/toLogin,重定向显示login页面
- 输入账户密码登录,设置token,返回cookie
问题:token设计,只是把user信息放到token,有泄露风险。
用户管理
相关类/文件:user.index.ftl、user.index.1.js、UserController.java、XxlJobUserDao.java、XxlJobUserMapper.xml
功能流程:常规的CRUD操作。
执行器管理
相关类/文件:JobGroupController.java
执行器启动自动注册
对象:每个app绑定一组执行器,一个执行器也可以绑定到多个app上。
功能流程:常规的CRUD操作。
任务管理
相关类/文件:JobInfoController.java
任务策略:路由策略、阻塞处理策略、调度过期策略
启动/停止流程:修改任务状态,计算下次调度时间,持久化,等待调度任务查询
功能流程:常规的CRUD操作、手动触发任务
调度日志查询
相关类/文件:JobLogController.java
功能流程:
查看调度信息,包括执行时间、执行器、执行结果。查询调度中心数据。
查看详细执行日志(logDetailCat),向执行器发送查询日志请求。
logKill接口功能,发送kill命令给执行器,用来终止正在执行的任务。触发子任务(如果有)。
清理日志,只清理调度中心的数据。
代码管理
相关类/文件:JobCodeController.java
功能流程:
存储任务代码,自动删除30次以前的修改记录。
api接口
用于与执行器通讯,包括回调执行结果、注册执行器、移除执行器
相关类/文件:JobApiController
回调执行结果:
- 查找任务日志(每次调度一个日志)
- 新增日志中带code,用于避免调度中心重复记录
触发子任务(如果有)
- JobTriggerPoolHelper
- 触发过程是异步
- 初始化一个任务日志joblog
- 发送joblog给执行器
- 执行器将joblog放入执行队列jobthread
- 更新日志状态并持久化
调度任务
相关类/文件:thread目录
调度流程
进程启动任务调度线程(JobScheduleHelper.scheduleThread)
启动scheduleThread线程,每5s执行一次
- 根据配置,计算每次调度最大量
- 启动ringThread,每1s执行一次
- 用户注册任务(JobInfoController.add())
用户启动任务(JobInfoController.start())
- 修改任务状态为启动,并制定下次运行时间
scheduleThread任务
- 获取数据库锁(保证只有一个调度任务在执行)
- 获取本次调度的任务列表(预先读取一部分数据 5s)
执行任务列表
- 如果任务已经过期 5s,根据过期策列,马上触发任务或者跳过
- 如果任务已经到期,马上执行,并且如果下次执行也在下个5s内,放入ringThread
- 如果任务5s内到期,放入ringThread
问题:
- 是否会重复执行任务?不会,ringThread只负责执行,不修改任务计划
分成5s和1s的任务是为了解决什么问题?减少DB查询次数
触发任务
如果是慢任务(超时次数>10),放入慢线程池,否则放入快线程池
- 慢任务计数器每分钟清空一次,执行时间超过500ms的任务计入计数器
- 获取任务详情,任务分片(如果有)
- 生成任务日志,设置执行策略,获取执行地址
发送任务给执行器执行
- 找到任务执行JobThread以及jobHandler,jobid:JobThread:jobHandler:job=1:1:1:N
- 如果JobThread还有job在执行,根据阻塞策略处理,覆盖、丢弃或序列等待
- 启动JobThread线程
- 把任务放入JobThread队列,判断job重复(应该提前到请求入口)
JobThread线程执行
- 从队列获取job
- 创建日志文件
- 存储任务日志
错误任务监控
相关类/文件:JobFailMonitorHelper、JobCompleteHelper
- 状态为“运行中”,且执行器掉线,把任务状态修改成失败。JobCompleteHelper.monitorThread
- 查询所有状态为fail的任务,尝试重试,并报警。JobFailMonitorHelper.monitorThread
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。