需求背景

目前各服务里经常会有定时任务相关需求,而定时任务通常要求同时只有一个任务执行,为了保证定时任务高可以通常也需要主备部署,导致开发定义任务时需要考虑锁竞争关系,以及考虑任务执行状态(成功、失败、重试等)。因此考虑实现一个统一的分布式任务调度服务,解决如下问题:

  • 支持一次性执行任务(一次性任务可以延迟执行);
  • 支持cron方式定时执行任务;
  • 任务分布式执行,高可用支持;
  • 支持简单任务状态统一监控(记录执行状态);
  • 支持任务重试机制。
  • 技术调研&选型

machinery(开源分布式任务调度框架)

machinery 是一个基于消息队列的分布式任务调度框架,由Server、broker、worker、backend 这么几个概念组成:

  • Server:业务模块,生成具体任务,可根据业务逻辑中,按交互进行拆分;
    Broker:存储具体序列化后的任务,machinery中目前支持到Redis, AMQP,和SQS;
    Worker:工作进程,负责消费者功能,处理具体的任务;
    Backend:后端存储,用于存储任务执行状态的数据;
    使用使用Server 作为任务生产和任务触发,backend 用作任务运行状态结果存储, machinery分布式框架不能满足定时触发的需求,因此还需要引入cron 定时任务框架,该定时任务框架是基于本地时间的定时任务框架,因此还需要结合分布式锁来保证同时只能触发一次任务。因此整体设计方案大致如下:

    由上图我们可以看到系统主要由2部分组成,分布式任务中心和客户端。

分布式任务中心

分布式任务中心用来管理任务、监控、调度、监听任务执行结果等。

  • 任务管理:增删查改定时执行任务
  • 定时任务监控:监控新的待执行任务,发现后创建新的触发器,失效删除后的定时任务配置
  • 推送待执行的任务到消息队列
  • 监听任务执行结果
  • 接收客户端主动触发推过来的异步任务。

客户端

客户端是分布式任务执行的组成单元,通过监听自己能执行的任务队列,来执行任务

  • 任务接收器:接收到任务后将任务分配给worker执行
  • 任务执行woker: 负责执行具体的任务
  • 执行结果推送:将任务执行结果推送到消息队列
  • 一致性任务触发: 部署异步任务只需满足某个条件时,就触发到消息队列中。

任务参数

任务参数1: {“name”:“task1”,“params”:[“params1=x1”,“params2=x2”], “cron_time”:“*/1 * * * ?”}


业务A 任务管理器 数据库 1.1 创建定时任务 1 1.2 保存定时任务配置 2 loop [监听任务创建事件端口] 业务A 任务管理器 数据库


定时任务创建器 数据库 任务触发器 任务队列 2.1 分布式锁 1 2.2 查询定时任务配置 2 2.3 创建定时触发器 3 loop [定时任务创建循环] 2.4 定时创建任务并推送 4 loop [定时触发任务] 定时任务创建器 数据库 任务触发器 任务队列


任务执行器 任务队列 任务结果队列 3.1 读取任务 1 3.2 执行任务 2 3.3 推送任务执行结果 3 loop [监听任务队列消息] 任务执行器 任务队列 任务结果队列


结果处理器 任务结果队列 数据库 4.1 读取任务结果 1 4.2 保存任务结果 2 loop [监听任务结果队列消息] 结果处理器 任务结果队列 数据库