1、调度系统概述

1.1、调度系统介绍
  • 含义:在指定时间协调器通过分布式执行器并行执行任务。

(1)目标

分布式环境下处理任务调度,在基于给定的时间点,给定的时间间隔或者给定执行次数自动的执行任务。

(2)作用

  • 分布式调度
  • 作业高可用
  • 最大限度利用资源

轻量级 分布式任务调度系统 python 分布式任务调度中心_分布式锁

(3)常见调度方案

轻量级 分布式任务调度系统 python 分布式任务调度中心_线程池_02

1.2、分布式调度平台设计目标

(1)强一致性

(2)服务高可用、系统稳健:保证服务器的正常工作

(3)弹性扩容:保证整体调度效率

(4)作业接入极简:任务创建尽可能简单化

(5)可视化管理后台:监控及管理,调度平台产品化

1.3、分布式任务调度轻量级架构设计

轻量级 分布式任务调度系统 python 分布式任务调度中心_分布式_03

(1)task-manager:管理作业

(2)task-center:即调度中心,向节点分配作业

(3)Zookeeper:分布式协调工具,信息存储

(4)Job-executor:执行器,实现具体的业务逻辑

(5)DB:管理元数据

2、DolphinScheduler架构设计

2.1、DolphinScheduler1.x系统架构说明

轻量级 分布式任务调度系统 python 分布式任务调度中心_java_04

(1)MasterServer

MasterServer 采用分布式无中心设计理念,MasterServer 主要负责 DAG 任务切分、任务提交监控, 并同时监听其它 MasterServer 和 WorkerServer 的健康状态

MasterServer 服务启动时向 Zookeeper 注册临时节点,通过监听 Zookeeper 临时节点变化来进行容错处理。 MasterServer 基于 netty 提供监听服务。

  • 主要服务及功能说明:

①Distributed Quartz 分布式调度组件,主要负责定时任务的启停操作,当 quartz 调起任务后, Master 内部会有线程池具体负责处理任务的后续操作

②MasterSchedulerThread 是一个扫描线程,定时扫描数据库中的 command 表,根据不同的 命令类型 进行不同的业务操作

③MasterExecThread 主要是负责 DAG 任务切分、任务提交监控、各种不同命令类型的逻辑处理 ④MasterTaskExecThread 主要负责任务的持久化

(2)WorkerServer

WorkerServer 也采用分布式无中心设计理念,WorkerServer 主要负责任务的执行和提供日志服务。 WorkerServer 服务启动时向 Zookeeper 注册临时节点,并维持心跳。Server 基于 netty 提供监听服 务。

  • 主要服务及功能说明:

① FetchTaskThread 主要负责不断从 Task Queue 中领取任务,并根据不同任务类型调用 。

②TaskScheduleThread 对应执行器

③LoggerServer 是一个 RPC 服务,提供日志分片查看、刷新和下载等功能

(3) ZooKeeper

系统中的 MasterServer 和 WorkerServer 节点都通过 ZooKeeper 来进行集群管理 和容错

系统基于 ZooKeeper 进行事件监听和分布式锁

(4)Task Queue

提供任务队列的操作,目前队列也是基于 Zookeeper 来实现。由于队列中存的信息较少,不必担心队 列里数据过多的情况,实际上我们压测过百万级数据存队列,对系统稳定性和性能没影响。

(5)Alert

提供告警相关接口,接口主要包括告警两种类型的告警数据的存储、查询和通知功能。

(6)API

API 接口层,主要负责处理前端UI层的请求。该服务统一提供 RESTful api 向外部提供请求服务。 接口 包括工作流的创建、定义、查询、修改、发布、下线、手工启动、停止、暂停、恢复、从该节点开始执 行等等。

(7)UI

系统的前端页面,提供系统的各种可视化操作界面。

2.2、架构设计思想

(1)中心化思想

  • 含义:分布式集群中的节点按照角色分工,大体上分为两种角色:Master&slave

轻量级 分布式任务调度系统 python 分布式任务调度中心_分布式_05

①Master :主要负责任务分发监督 Slave 的健康状态,可以动态的将任务均衡到 Slave 上,以致 Slave 节点不至于“忙死”或”闲死”的状态。

②Worker:主要负责任务的执行工作并维护和 Master 的心跳,以便 Master 可以分配任务给 Slave。

  • 主要问题
  • Master单点故障
  • Master内存过载

(2)去中心化 - 动态中心化

  • 含义:集群中的管理者是被动态选择出来的,而不是预置的,并且集群在发生故障的时候,集群的节点会自发的举行"会议"来选举新的"管理者"去主持工作。

轻量级 分布式任务调度系统 python 分布式任务调度中心_java_06

  • DolphinScheduler去中心化:Master/Worker 注册到 Zookeeper 中,实现 Master 集群和 Worker 集群无中心,并使用 **Zookeeper 分布式锁来选举其中的一台 Master 或 Worker 为“管理 者”**来执行任务。

(3)分布式锁

轻量级 分布式任务调度系统 python 分布式任务调度中心_云计算_07

  • DolphinScheduler使用 ZooKeeper 分布式锁来实现同一时刻只有一台 Master 执行 Scheduler,或者只有 一台 Worker 执行任务的提交。

(4)线程不足循环等待问题

  • 含义:如果一个 DAG 中没有子流程,则如果 Command 中的数据条数大于线程池设置的阈值,则直接 流程等待或失败。 如果一个大的 DAG 中嵌套了很多子流程,如下图则会产生“死等”状态

轻量级 分布式任务调度系统 python 分布式任务调度中心_分布式锁_08

①问题说明

上图中 MainFlowThread 等待 SubFlowThread1 结束,SubFlowThread1 等待 SubFlowThread2 结 束, SubFlowThread2 等待 SubFlowThread3 结束,而 SubFlowThread3 等待线程池有新线程,则整 个 DAG 流程不能结束,从而其中的线程也不能释放。这样就形成的子父流程循环等待的状态。此时除 非启动新的 Master 来增加线程来打破这样的”僵局”,否则调度集群将不能再使用。

(2)解决方案

DolphinScheduler增加一种资源不足的 Command 类型,如果线程池不足,则将主流程挂起。这样线程池就有了新的线程,可以让资源不足挂起的流程重新唤醒执行。

2.3、容错设计
  • 容错分为服务宕机容错和任务重试,服务宕机容错又分为 Master 容错和 Worker 容错两种情况

(1)Master服务器宕机容错

  • Master作用: Master 监控其他 Master 和 Worker 的目录,如果监听到 remove 事件,则会根据具体的业务逻 辑进行流程实例容错或者任务实例容错。

轻量级 分布式任务调度系统 python 分布式任务调度中心_分布式_09

  • Master容错示意图

轻量级 分布式任务调度系统 python 分布式任务调度中心_线程池_10

  • ZooKeeper Master 容错完成之后则重新由 DolphinScheduler 中 Scheduler 线程调度,遍历 DAG 找到”正 在运行”和“提交成功”的任务,对”正在运行”的任务监控其任务实例的状态,对”提交成功”的任务需要判 断 Task Queue 中是否已经存在,如果存在则同样监控任务实例的状态,如果不存在则重新提交任务实 例。

(2)Worker宕机容错

轻量级 分布式任务调度系统 python 分布式任务调度中心_线程池_11

  • Master Scheduler 线程一旦发现任务实例为 ”需要容错” 状态,则接管任务并进行重新提交。
  • 注意事项:由于 ”网络抖动” 可能会使得节点短时间内失去和 ZooKeeper 的心跳,从而发生节点的 remove 事件。对于这种情况,我们使用最简单的方式,那就是节点一旦和 ZooKeeper 发生超时连接,则直接 将 Master 或 Worker 服务停掉。

(3)任务失败重试

  • 重试措施:每一个业务节点 都可以配置失败重试的次数,当该任务节点失败,会自动重试,直到成功或者超过配 置的重试次数。逻辑节点不支持失败重试。但是逻辑节点里的任务支持重试。

①任务失败重试:是任务级别的,是调度系统自动进行的,比如一个 Shell 任务设置重试次数为 3 次,那么在 Shell 任务运行失败后会自己再最多尝试运行3次

②流程失败恢复:是流程级别的,是手动进行的,恢复是从只能从失败的节点开始执行或从当前节点开 始执行

③流程失败重跑:是流程级别的,是手动进行的,重跑是从开始节点进行