Apache DolphinScheduler 2.X保姆级源码解析,中国移动工程师揭秘服务调度启动全流程

2022年1月,科学技术部高新技术司副司长梅建平在“第六届中国新金融高峰论坛”上表示,当前数据量已经大大超过了处理能力的上限,若信息技术仍然是渐进式发展,则数据处理能力的提升将远远落后于指数级增长的数据量。因此,在一段时期内,数据处理能力与效率的提升仍将是大数据发展要面对的技术难点。
随着5G、物联网等网络信息技术的快速发展以及应用的快速增长,数据量也呈指数级增长,纵观运营商整个大数据开发的链路上,在各个环节都会出现各种严峻的问题,随着数据任务调度量级日益增大,阻碍数据正确且高效地发挥价值,对运营商数据团队提出严峻挑战。
在大数据领域,越来越多的企业拥抱开源软件,在这个背景下,我们针对数据调度工具如何正确选型?
中国移动云能力中心软件开发工程师徐海辉表示:古语云“工欲善其事必先利其器”,如果你正处于观望/不知如何下手/即将参与开源项目的小伙伴,我建议可以先从一个优秀的开源社区源代码的入手,我在中国移动目前主要负责数据服务,这次在 Apache DolphinScheduler 4月 Meetup 上为大家带来DolphinScheduler源码2.X解析,希望你有所收获。
本次演讲主要包含四个部分:
开篇与源码环境准备
服务启动流程
任务执行流程
个人思考与总结

徐海辉
中国移动云能力中心 软件开发工程师。从事大数据基础平台开发,主要负责中国移动Hadoop大数据平台组件Ranger 、移动云Lake House 产品的研发
关键词:Apache DolphinScheduler源码2.X解析、源码环境准备、服务启动、任务执行
Apache DolphinScheduler 源码下载链接:
https://dolphinscheduler.apache.org/zh-cn/download/download.html
01 开篇与源码环境准备
Apache DolphinScheduler是一个基于java开发的开源分布式工作流调度系统。致力于可视化操作任务及工作流之间的依赖关系,并可视化整个数据流过程;解决数据处理流程中错综复杂的依赖关系。
01 入手DolphinScheduler需要考虑的问题
开源分布式的工作原理?
工具可视化是体现在哪里?
Master和Worker之间如何通信?
怎么体现工作流之间的依赖关系?
“Show me the code”
其实在这个过程中需要考虑的问题有很多,我们不妨从官方给的架构图先简单梳理一下,然后通过实际的使用,再去研究源码,一套组合拳下来就差不多了。
02 DolphinScheduler架构图
话不多说,开撸!
4个由源码启动的服务是:UI、MasterServer、WorkServer、AlertServer(还有LoggerServer图里面没有体现)

MasterServer & WorkServer依赖于Zookeeper协调服务中心注册
MasterServer & WorkServer 1-N组成集群,分别是单独的服务和进程
执行任务支持的插件:Flink、Shell、Subflow、SQL、Procedure、Python、MR、Spark、Dependent等等
03 预先必备知识
- Netty
一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端
- Zookeeper
一个分布式的,开放源码的分布式应用程序协调服务,它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
- 分布式锁
为了解决单机部署情况下的并发控制锁策略失效这个问题,需要一种跨机器的互斥机制来控制共享资源的访问
- Quartz
定时自动执行任务
- 多线程
很多小伙伴不明白Master和Worker之间是怎么通信的,DolphinScheduler是基于Netty框架来实现的。这里可以拓展一下,服务器之间的通信还有很多方式:
- HTTP
HTTP:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。
- REST API
REST API通信是通过JSON格式的字符串进行数据传输的,而字符串是可以在网络中穿透防火墙的。也就是说,REST API可以穿透防火墙。同时字符串也可以不用受开发语言的限制,可以同时完成后端与WEB,后端与APP(Android,IOS)之间的通信。
- RPC
RPC通信又称远程过程调用,在内网中速度非常快,效率高。
如下图是准备相关环境的部署,并且我还提供了一个远程Debug的方式,这个不难理解,比如你想调试API,在启动过程中,它肯定会调用脚本,你只需要在脚本里面添加 Debug启动的一些参数,就可以进行一个远程的Debug。

像框框里面的数字实际上是服务的端口号,如果跟本地服务/其他组件端口之间有冲突的话,对它可以进行一个修改。
02 服务启动流程
01 Master启动流程
MasterServer采用分布式无中心设计理念,基于Netty提供监听服务。
MasterServer服务启动时向Zookeeper注册临时节点,通过监听Zookeeper临时节点变化来进行容错处理。
MasterServer主要负责 DAG 任务切分、任务提交监控,并同时监听其它MasterServer和WorkerServer的健康状态。
启动步骤
启动Netty 服务端服务
注册到Zookeeper
启动Event处理器
启动scheduler定时任务
启动StateWheel处理器
↓↓↓源码一览↓↓↓

对应路径里面存放了MasterServer.java的类,里面有对应的main方法

执行完构造函数后,会启动run方法及其各个组件

这里会提前构造参数

调用start方法启动

注册元数据信息到Zookeeper上面,值得一提的是这里采用的是临时路径,比如说在过程中服务断开了或者session过期,临时路径过一段时间会自己去Delete掉。

启动调度服务

启动Quartz框架,启动完之后相当于是一个独立的服务.
小结:
第一步是注册这个Netty
第二步是向Zookeeper注册数据信息。
第三步是启动相关组件和调度任务
第四步是启动Quartz框架
02 Worker启动流程
WorkerServer采用分布式无中心设计理念,WorkerServer基于Netty提供监听服务。
WorkerServer主要负责任务的执行和提供日志服务。WorkerServer服务启动时向Zookeeper注册临时节点,并维持心跳。
**拓展:**防止出现断开、关闭等突发状况,这里会选择注册临时节点做出Delete动作。
启动步骤
启动Netty 服务端服务
注册到Zookeeper
维护workserver节点状态
启动TaskExecuteThread
启动RetryReportTaskStatusThread
↓↓↓源码一览↓↓↓

找到WorkServer.java中的main方法,进程代码也位于DolphinScheduler-Server模块下面

启动Netty服务,过程中也会提供一些端口,以便和其他进程交互

向Zookeeper注册信息,其中WorkerregistryClient调用了Zookeeper的代码

主要是处理和创建一些节点

启动组件,WorkerManagerThread主要是管理Master发过来的任务

启动组件,RetryReportTaskStatus主要是给Master反馈信息
03 任务执行流程
首先我们可以从UI界面具体分析一些工作流是如何运行的?

DolphinScheduler-api : ExecutorController.java → startProcessInstance() → createCommand() →写入表 t_ds_command
然后通过代码的跟踪去看一下

位于DolphinScheduler-API模块下的controller里面

Start-process-instance会调用ExecProcessInstance方法

通过一系列的执行,最终会解析一些参数

解析完之后会生成一条记录(Create Command)
接下来MasterServer会不定时扫描表里面的记录,然后拉取出来,最后构建流程的实例
定时任务轮询获取
Dolphinscheduler-server: MasterSchedulerService.java → scheduleProcess() → findOneCommand() → 创建ProcessInstance
构建DAG并分发到worker
WorkflowExecuteThread.java → startProcess() → buildFlowDag() → submitPostNode() → submitStandByTask() → submitTaskExec()
TaskProcessor.java → dispatchTask() → 放入TaskPriorityQueue
TaskPriorityQueueConsumer.java: → dispatch()
ExecutorDispatcher.java → dispatch()
NettyExecutorManager.java → execute() →build command → doExecute() → ettyRemotingClient.send()

Master启动完之后会不停拉取命令,然后解析完之后分发给Worker

可以看一下它的run方法

Scheduleprocess方法去找一条命令→Findonecommand,找到之后对它进行解析,创建工作流实例

交给WorkflowExecuteThread线程执行

WorkflowExecuteThread run方法启动之后提交一个节点

放到优先级队列里面,构造处理的一些参数,通过Netty分发
Worker接收任务并执行
NettyClientHandler.java → channelRead() → processReceived() → TaskExecuteProcessor.java → process() → workerExecuteQueue.offer()
WorkerManagerThread.java → workerExecuteQueue.take()
TaskExecuteThread.java → build taskRequest → taskChannel.create(taskRequest) →AbstractTask init() → handle()

通过taskExcutethread执行

通过代码跟踪,我们发现是调用队列里面的offer方法

通过channelRead方法接收Master发过来的信息,然后放在队列里面

通过while循环不停的处理队列里的任务

任务执行的参数都放在taskExcutiontext里面

TaskChannel主要识别脚本任务类型(Flink、Shell、Python等脚本)

任务执行完之后,通过ResponseCommand收集完信息反馈给Master
04思考与总结
01 优化返回方式
我们看源码的过程当中发现,比如说在DolphinSchedulerr-api跟前端交互接口的时候,请求参数返回的时候,它没有用bean来进行处理,什么意思呢?就是说它参数比较混乱,比如说自己的一些恶应用要接入 DolphinScheduler,或者说后续社区要提供一些SDK,有bean的方式进行参数传递是比较好的。

02 表格式统一
还有一个在调研的过程当中,这个表的命名还有优化空间,表的命名格式有一些不同,比如说一些关系表,它后面加了 relation,然后有一些是加在前面的。

03 命名不友好

在看源码的过程当中,发现它的一些命名是不太友好的,如上图
05拥抱开源
你如果从事软件开发,你有可能会想花时间去打造一下属于你自己的IP,比如说你负责具体某个组件,成为核心开发者。
01 我们为什么要去学习开源?
1、提升技术功底:学习源码里的优秀设计思想,比如疑难问题的解决思路,一些优秀的设计模式,整体提升自己的技术功底,比如说在DS里面,用了大量的线程去处理一些Event,然后使用了去中心化,还有使用队列,优先级队列等等
2、深度掌握技术框架:源码看多了,对于一个新技术或框架的掌握速度会有大幅提升,比如说你要去学习 DS或者对它进行一个二次开发,你肯定要去了解一下其他知识,比如说Netty,还有Zookeeper
3、快速定位线上问题:遇到线上问题,特别是框架源码里的问题(比如bug),能够快速定位
4、拥抱开源社区:参与到开源项目的研发,结识更多大牛,积累更多优质人脉看源码
02 在开源社区的学习方法
先使用:先看官方文档快速掌握框架的基本使用
抓主线:找一个demo入手,顺藤摸瓜快速看一遍框架的主线源码,画出源码主流程图,切勿一开始就陷入源码的细枝末节,否则会把自己绕晕,凭经验猜
画图做笔记:总结框架的一些核心功能点,从这些功能点入手深入到源码的细节,边看源码边画源码走向图,并对关键源码的理解做笔记,把源码里的闪光点都记录下来,后续借鉴到工作项目中,理解能力强的可以直接看静态源码,也可以边看源码边debug源码执行过程,观察一些关键变量的值
整合总结:所有功能点的源码都分析完后,回到主流程图再梳理一遍,争取把自己画的所有图都在脑袋里做一个整合
参与贡献
随着国内开源的迅猛崛起,Apache DolphinScheduler 社区迎来蓬勃发展,为了做更好用、易用的调度,真诚欢迎热爱开源的伙伴加入到开源社区中来,为中国开源崛起献上一份自己的力量,让本土开源走向全球。
参与 DolphinScheduler 社区有非常多的参与贡献的方式,包括:

贡献第一个PR(文档、代码) 我们也希望是简单的,第一个PR用于熟悉提交的流程和社区协作以及感受社区的友好度。
社区汇总了以下适合新手的问题列表:https://github.com/apache/dolphinscheduler/issues/5689
非新手问题列表:https://github.com/apache/dolphinscheduler/issues?q=is%3Aopen+is%3Aissue+label%3A"volunteer+wanted"
如何参与贡献链接:https://dolphinscheduler.apache.org/zh-cn/docs/development/contribute.html
来吧,DolphinScheduler开源社区需要您的参与,为中国开源崛起添砖加瓦吧,哪怕只是小小的一块瓦,汇聚起来的力量也是巨大的。
参与开源可以近距离与各路高手切磋,迅速提升自己的技能,如果您想参与贡献,我们有个贡献者种子孵化群,可以添加社区小助手微信(Leonard-ds) ,手把手教会您( 贡献者不分水平高低,有问必答,关键是有一颗愿意贡献的心 )。
添加小助手微信时请说明想参与贡献。
来吧,开源社区非常期待您的参与。
Apache DolphinScheduler 2.X保姆级源码解析,中国移动工程师揭秘服务调度启动全流程的更多相关文章
- android源码解析(十七)-->Activity布局加载流程
版权声明:本文为博主原创文章,未经博主允许不得转载. 好吧,终于要开始讲讲Activity的布局加载流程了,大家都知道在Android体系中Activity扮演了一个界面展示的角色,这也是它与andr ...
- [源码解析] 并行分布式任务队列 Celery 之 消费动态流程
[源码解析] 并行分布式任务队列 Celery 之 消费动态流程 目录 [源码解析] 并行分布式任务队列 Celery 之 消费动态流程 0x00 摘要 0x01 来由 0x02 逻辑 in komb ...
- Dubbo源码解析(一)服务发现
一.Dubbo源码模块 官网地址 源码地址 1.1 源码模块组织 Dubbo工程是一个Maven多Module的项目,以包结构来组织各个模块. 核心模块及其关系,如图所示: 1.2 模块说明 dubb ...
- sqler sql 转rest api 源码解析(一)应用的启动入口
sqler sql 转rest api 的源码还是比较简单的,没有比较复杂的设计,大部分都是基于开源 模块实现的. 说明: 当前的版本为2.0,代码使用go mod 进行包管理,如果本地运行注意gol ...
- dubbox源码分析(一)-服务的启动与初始化
程序猿成长之路少不了要学习和分析源码的.最近难得能静得下心来,就针对dubbox为目标开始进行源码分析. [服务提供方] 步骤 调用顺序 备注 容器启动 com.alibaba.dubbo.conta ...
- Netty源码分析 (三)----- 服务端启动源码分析
本文接着前两篇文章来讲,主要讲服务端类剩下的部分,我们还是来先看看服务端的代码 /** * Created by chenhao on 2019/9/4. */ public final class ...
- ss-libev 源码解析local篇(1): ss_local的启动,客户端连入
学习研究ss-libev的一点记录(基于版本3.0.6) ss_local主要代码在local.c中,如果作为一个库编译,可通过start_ss_local_server启动local server. ...
- Android源码解析系列
转载请标明出处:一片枫叶的专栏 知乎上看了一篇非常不错的博文:有没有必要阅读Android源码 看完之后痛定思过,平时所学往往是知其然然不知其所以然,所以为了更好的深入Android体系,决定学习an ...
- springcloud源码解析(目录)
springcloud是一个基于springboot的一站式企业级分布式应用开发框架.springboot为其提供了创建单一项目的便利性,springcloud组合了现有的.常用的分布式项目的解决方案 ...
随机推荐
- 2020级C++实验课-期末机考模拟考题解
做这个题解的理由很简单,有很多同学想写但是不会写,凑巧我写了,所以搞个题解. 顺序就是题单里的顺序(界面左上角菜单切换文章,右上角目录方便查看) 1:黑马白马 题意: 随机得到一个数字,如果是偶数,则 ...
- 2020级cpp机考模拟题A卷-#题解1
为了各位朋友的身心健康(不是),我们按照题目难度顺序来写题解. 第一次写题解,希望多点包容和鼓励(恬不知耻 1:谁先输出-4 题意: 输入3个整数,按从大到小的顺序输出,每两个数字间加一个空格. 题解 ...
- 安装Zookeeper到Linux
系统版本:Ubuntu 16.04.5 LTS 软件版本:apache-zookeeper-3.5.8 硬件要求:无 1.安装依赖 Zookeeper需要JDK的支持. 注:需要先去JDK官网下载安装 ...
- Pandas 分组聚合 :分组、分组对象操作
1.概述 1.1 group语法 df.groupby(self, by=None, axis=0, level=None, as_index: bool=True, sort: bool=True, ...
- 《Unix 网络编程》11:名字和地址转换
名字和地址转换 系列文章导航:<Unix 网络编程>笔记 域名系统 简介 域名系统主要用于主机名字和 IP 地址之间的映射.主机名可以是: 简单名字,如:centos01 全限定域名(FQ ...
- 用树莓派USB摄像头做个监控
[前言] 看着阴暗的角落里吃灰噎到嗓子眼的树莓派,一起陪伴的时光历历在目,往事逐渐涌上心头,每每触及此处,内心总会升腾起阵阵怜悯之情... 我这有两个设备,一个是积灰已久的树莓派,另一个是积灰已久的U ...
- 开源的.Net 工作流引擎Elsa初试——创建工作流服务器和图形化工作流配置管理应用
微软的Workflow Foundation基于.Net Framework,并且没有向.Net Core迁移的计划.我们的很多项目使用了工作流引擎,这些项目向.Net Core以及更高版本迁移时遇到 ...
- [学习笔记]使用Docker+Jenkin自动化流水线发布.Net应用
使用Docker容器方案可以快速安全地将项目部署到客户的服务器上,作为公司项目,需要解决两个问题: 1. 需要搭建一个私有的Docker仓库,以便安全的存储镜像 2. 需要一套自动化发布方案,实现代 ...
- 互联网公司目标管理OKR和绩效考核的误区
最近看了一篇关于「谷歌放弃OKR,转向全新的GRAD系统」的文章,我转到了研发效能DevOps的微信群里,结果引起了大家热烈的讨论,正好我们也在使用 OKR,所以也来谈谈我的理解以及我们应用起来的实际 ...
- 如何在Vue项目中,通过点击DOM自动定位VScode中的代码行?
作者:vivo 互联网大前端团队- Youchen 一.背景 现在大型的 Vue项目基本上都是多人协作开发,并且随着版本的迭代,Vue 项目中的组件数也会越来越多,如果此时让你负责不熟悉的页面功能开发 ...