Loading

Dolphin Scheduler学习

前言

基于3.2.2-release版本

架构图

DS的架构图貌似年久失修,和代码已经有一些偏差了,不过还是可以用作参考。

img

官方文档:Dolphin Scheduler 系统架构设计

Master Worker之间的服务发现

DS抽象了一个Registry作为Master和Worker节点统一的注册处,提供如下核心能力:

  1. putEphemeral(path, value):向某个path写入值,临时写入,写入节点down掉后删除
  2. put(path, value, deleteOnDisconnected):上一个的通用版本
  3. get(path):获取写入值
  4. subscribe(path, listener):监听某一个path下的数据增删改查
  5. addConnectionListener(listener):监听到注册处的连接,重连、断开等都有回调
  6. ...

基本可以看出,这API是针对Zookeeper定的,Registry作为一个通用接口,项目中提供了几种不同的SPI实现:

img

Master和Worker启动时的数据流图如下:

img

Master如何调度任务

DS中的任务有如下角色:

  • Process:即整个DAG,是定时调度的基本单元
  • Task:任务,工作流中的一个单独节点,是任务分派的基本单元,也是Worker执行的东西

它们又被拆分成定义(Definition)和实例(Instance),定义表保存了DAG和任务的基本属性,实例则是它们实际的运行记录。

DS可以看作一个分布式定时任务调度框架,只不过它调度的任务是一个大型的DAG,DAG中每个节点都需要被分派到不同的Worker节点上,这些节点可能具有某种程度的并行(考虑DAG的拓扑排序中先后顺序可被调换的那些)

引入两个概念:

  • Schedule:基于cron触发定时任务
  • Dispatch:执行定时任务时,将DAG的Task节点分发到Worker上

Schedule:从Cron到DAG调度

DS中定义了scheduler-plugin来定义一套标准的调度器API,且默认提供了基于quartz的去中心化分布式定时任务框架实现的scheduler。

scheduler-api定义了如下功能:

  1. insertOrUpdateScheduleTask:插入或更新调度任务
  2. deleteScheduleTask:删除调度任务

下图是DS中任务调度的时序图:

DS并非直接等待Scheduler调度后就直接进行任务分派,Scheduler调度Master后只是执行一个非常轻量的Command创建功能,Command相当于一个队列,它保存了所有立即要进行执行的DAG,Master中有守护线程不断地扫描Command执行拆分。

Dispatch:DAG中的Task分派

  1. 每一个Master在启动时都会启动一个MasterSchedulerBootstrap,负责不间断的扫描Command

    Master之间貌似通过slotNumber和Command求余,让不同的Master之间处理的Command不相干,从而实现无锁化。slot也是服务发现板块中Master注册到注册中心里的一个属性,目前还不知道如何保证failover时slot变更和扫描command之间的原子性,否则在slot信息变动时可能会重复调度。

  2. 扫描到command后,为每一个command创建一个WorkflowExecuteRunnable,其中封装了任务调度的逻辑

  3. 异步启动工作流,并注册超时检查

  4. 拆分DAG中的Task,为每一个Task创建TaskInstance

  5. 不断的取出无前置节点,或前置节点已经完成的Task,放置到standByTask中,并使用某种负载均衡策略(默认low weight),向worker调用rpc分派任务

  6. 一旦worker报告任务状态(反向rpc),重新执行5,直到DAG中所有Task都完成

如何Failover

DS的插件(SPI)如何实现

RPC是如何实现的

posted @ 2025-06-17 22:59  于花花  阅读(89)  评论(0)    收藏  举报