以数据采集系统为例,简单记录一下如何设计一个相对可用的任务调度/分发系统
目标
我们设计的目标是一个数据采集系统,有以下目标
- 用户可以提交任务。(new job)
- 用户可以按照特定的规则配置一类Job的运行规则(JobRule),该执行规则结合执行结果,可在动态生成子任务,子任务同样有自己的JobRule
- 任务是树状的,即存在parentJob与children之间的关系,parent可在运行过程中,根据远端响应以及任务的配置,动态的生成不定数量的子任务,该过程是可嵌套循环下去的
- 任务存在状态 Pending、Running、Finished、Error、Warning等
- 任务有输出
初步流程设计
几种角色
- User: 提交初始任务
- Dispatcher: 调度任务到相关队列
- Executor: 实际执行任务
- User将任务提交到Waiting Pool
- Dispatcher按照一定的规则,从Waiting Pool中获取新增加的Job,将其分配到JobQueue中
- Executor从对应的JobQueue中获取新的任务(该Job将不会从队列中被移除,仅隐藏),创建JobSession。Session代表一个任务的一次执行。
- Executor尝试执行任务。
- 如果任务成功执行,则提交Job的执行结果。报告任务Session成功状态,并按照JobRule判断是否需要创建子任务,完成后将从JobQueue中移除该Job
- 如果失败,则LocalRetryCount++, 如果LocalRetryCount超过了本地可重试的上限,则标记该Session失败。等待该任务从JobQueue中自动恢复
mermaid图
调度流程
graph TD A[User] -->|Submit New Job To| B[Waiting Pool] B --> |Fetched By Dispatcher|C[JobDispatcher] C-->|Dispatch Job|D[JobQueue] D-->|Fetched By Executor| E[JobExecutor] E-->|Dynamic Generated Jobs|B
Executor执行流程
graph TD A[Job]-->|SetJobRunSession|B[JobWithSession] B-->|TryRunJobWithSession|C{ExecutionResult?} C-->|Ok|D[StoreData] D-->|TryGenerateChild|E[Waiting Pool] C-->|Error or Exception|F{ExceedLocalRetryCount} F-->|Yes|G[ReportSessionErrorToServer] F-->|No|B