1

分布式调度是高可用的关键,因此特别做研究。以功能/需求/问题为导向,逐个分析实现原理。

目录

  1. 项目解决了什么核心问题
  2. 与其他项目有什么区别和优势
  3. 功能架构
  4. 核心业务流程

    1. 执行器注册实现原理
    2. 任务注册实现原理
    3. 任务执行实现原理
  5. 异常场景处理

    1. 执行器执行过程中挂了怎么办
    2. 调度中心挂了怎么办
    3. 怎么保证任务只执行一次
    4. 调度中心和执行器怎么连接
    5. 同时有多个任务,执行器怎么处理
    6. 一个任务执行时间超时,执行器怎么处理
    7. 有的任务执行时间很长,有点短,怎么处理
    8. 怎么注册任务
    9. 怎么注册执行器
  6. 辅助的特性/功能

    1. 国际化 I18N
  7. 下阶段迭代特性/功能
  8. 发展迭代过程中标志性功能

服务接口

登录权限管理

对象: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

前端


一句话
12 声望1 粉丝

引用和评论

0 条评论