传统crontab痛点
- 机器故障, 任务停止调度, 甚至crontab配置都找不回来
- 任务数量多, 单机的资源耗尽, 需要人工迁移到其他机器
- 需要人工去机器上配置cron, 任务执行的状态不方便查看
分布式架构-核心要素
- 调度器: 需要高可用, 确保不会因为单点故障停止调度
- 执行器: 可扩展, 提供大量任务的并行处理能力
常见开源调度框架
- quartz
伪分布式设计
- 分布式网络环境不可靠, RPC异常属于常态
- Master下发任务RPC异常, 导致master与worker状态不一致
- worker上报任务RPC异常, 导致Master状态信息落后
异常case:
- 状态不一致: master下发任务给node1异常, 实际node1收到并开始执行
- 并发执行: master重试任务下发给node2, 结果node1与node2同时执行一个任务
- 状态丢失: master更新zookeeper中任务状态异常, 此时master宕机切换standby, 任务仍旧处于旧状态
分布式伪命题
- 但凡需要经过网络的操作, 都有可能异常
- 将应用状态放在存储中, 必然会出现内存与存储状态不一致
- 应用直接利用raft管理状态, 可以确保最终一致, 但成本太高
CAP理论- 常用于分布式存储
- C: 一致性, 写入后立即读到新值
- A: 可用性, 通常保障最终一致
- P: 分区容错性, 分布式必须面对网络分区
BASE理论- 常用于应用架构
- 基本可用
- 软状态
- 最终一致性
整体架构
- 利用etcd同步全量任务列表到所有的worker节点
- 每个worker独立调度全量任务, 无需与master产生直接rpc
- 各个worker利用分布式锁抢占, 解决并发调度相同任务的问题
Mater功能
- 任务管理Http接口: 新增, 修改, 查看, 删除
- 任务日志http接口: 查看任务执行历史日志
- 任务控制http接口: 提供强制结束任务的接口
- web管理界面: jquery+bootstrap, 前后端分离
Worker功能
- 任务同步: 监听etcd中/cron/jobs/目录变化
- 任务调度: 基于cron表达式, 触发过期任务
- 任务执行: 协程池并发执行多任务, 基于etcd分布式锁抢占
- 日志保存: 捕获任务执行输出, 保存到mongoDB