分布式crontab架构
1. 架构分析
1.1 传统crontab痛点
- 机器故障,任务停止电镀,甚至cron配置都找不回来
- 任务数量多,单机硬件资源有限,需要人工迁移到其他机器
- 需要人工去机器上配置cron,任务执行状态不方便查看
1.2 分布式架构的核心要素
- 调度器:需要高可用,确保不会因为单点故障停止调度
- 执行器:需要扩展性,提供大量任务的并行处理能力
1.3 常见开源调度架构
2. 分布式设计
分布式架构下的常见的RPC调用问题:
- 分布式网络环境不可靠,RPC异常属于常态
- master下发任务RPC异常,导致master与worker状态不一致
- worker上报任务RPC异常,导致master状态信息落后
异常case举例:
- 状态不一致:master下发任务给node1异常,实际上node1收到并开始执行
- 并发执行:master重试下发任务给node2,结果node1与node2同时执行一个任务
- 状态丢失:master更新zookeeper中任务状态异常,此时master宕机切换standby,任务仍处于旧状态
分布式伪命题:
- 但凡需要经过网络的操作,都可能出现异常
- 将应用状态放在存储中,必然会出现内存与存储状态不一致
- 应用直接利用raft管理状态,可以确保最终一直,但是成本太高
3. 架构设计
架构简化,减少有状态服务,秉承最终一致性
架构折衷,确保异常可以被程序自我治愈
4. 整体架构
4.1 架构模型
4.2 架构思路
利用etcd同步全量任务列表到所有worker节点
每个worker独立调度全量任务,无需与master产生直接rpc
每个worker利用分布式锁抢占,解决并发调度相同任务的问题
4.3 master节点设计
任务管理http接口:新建、修改、查看、删除任务
任务日志http接口:查看任务执行历史日志
任务控制http接口:提供去强制结束任务的接口
实现web管理界面:基于jquery+bootstrap的web控制台,前后端分离
4.4 worker节点设计
任务同步:监听etcd中/cron/jobs目录变化
任务调度:基于cron表达式计算,触发过期任务
任务执行:协程池并发执行多任务,基于etcd分布式锁抢占
日志保存:捕获任务执行输出,保存到mongoDB