达人专栏 | 还不会用 Apache Dolphinscheduler?大佬用时一个月写出的最全入门教程【三】

作者 | 欧阳涛 招联金融大数据开发工程师
02 Master启动流程
2.10 WorkFlowExecutorThread 里执行 Submit StandByTask 方法
SubmitStandByTask干了5件事情:
- 从ReadyToSubmitTaskQueue中取出TaskInstance。
- (这个TaskInstance是可以重试并且设定为强制成功了的)把task放到completeTaskMap以及taskInstanceMap,并从队列中移除。
- 如果这个task是首次执行的话,就会先从task和ProcessInstance中获取参数(varPool)【这一步的方法是GetPreVarPool】
- 获取这个task依赖结果【这一步的方法是GetDependResultForTask】
- 根据第4步获取的依赖结果,如果依赖结果为失败或者不执行,就从队列中移除,并且放到FailedTaskMap里的。如果依赖结果为成功则将执行SubmitTaskExec方法,同时会放到CompleteTaskMap。至于SubmitTaskExec做了哪些事情将在2.11中说明。
2.11 WorkFlowExecutorThread里执行SubmitTaskExec方法
SumbitTaskExec干了9件事情:
- PackageTaskInstance封装了TaskInstance,就是将TaskInstance和ProcessInstance进行了绑定,并且获取到了MainJar,ResourceList这些信息。
- 根据TaskType获取CommonTaskProcessor,这里采用SPI机制获取。如果想具体了解SPI机制的,可以百度搜索AutoService注解以及ServiceLoad进行详细了解。
- CommonTaskProcessor初始化,也就是将TaskInstance、ProcessInstance、ProcessService、MasterConfig传递给CommonTaskProcessor。
- 通知流程所在的主机,通过netty发送Host和HostUpdateCommand。
- 将CommonTaskProcessor的Action为submit(提交)状态。(这步极为重要)
- 放入到ValidMap,TaskInstanceMap,ActiveTaskProcessorMaps里。
- 将CommonTaskProcessor的Action设置成Run状态的。
- 将task以及ProcessInstance放入到StateWheelExecuteThread进行checkout。
- 如果这个task执行完成就添加到StateEvents队列中。
下一节讲述commonTaskProcessor的submit状态。
2.12 CommonTaskProcessor里执行Submit Task方法
回顾一下上节的第5步,CommonTaskProcessor的Action设置为Submit之后,
去ComonTaskProcessor的父类BaseTaskProcessor找Action方法,在Action方法中有个Switch结构,很明显会进入Submit方法,之后就进入本节所说的SubmitTask方法的了。
SubmitTask在这里干了三件事情:
- ProcessService。SubmitTaskWithRetry可以重复5次(MasterConfig.GetTask CommitInterval)提交task任务,最后在ProcessServiceImpl执行submitTask。
- 将此task的信息插入到TaskGroupQueue数据表中。
- DispatchTask下发任务,将Task任务下发到实现了TaskPriorityQueue接口的TaskPriorityQueueImpl中去。
在ProcessServiceImpl如何执行submitTask将在2.13中说明,同时DispatchTask下发做了那些事情,将在2.15中说明。
2.13 ProcessServiceImpl里执行SubmitTask方法
ProcessServiceImpl是属于Service模块的,SubmitTask主要干了2件事情:
- SubmitTaskInstanceToDB 将任务实例保存到数据库中,当然这里面有数据结构(TaskInstance)的变化,纯属业务的改变的。
- 如果此非结束状态,CreateSubWorkerProcess创建子流程,如果没有子流程,直接跳过2.14的内容。进入2.15。创建子流程做了哪些事情将在2.14中说明。
2.14 ProcessServiceImpl里执行CreateSubWork Process方法
创建子流程需要干6件事情:
- FindWorkProcessMapByParent查找父流程与task绑定的ProcessInstanceMap,是流程实例与Task关系的表。
- SetProcessInstanceMap。设置刚刚查找的ProcessInstanceMap,如果能找到以前跑的ProcessInstanceMap,更新这个ProcessInstanceMap,如果没有找到就创建新的ProcessInstanceMap,并插入到数据库中。
- CreateSubProcessCommand,根据参数,父流程等创建子流程命令的(SubProcessCommand)。
- UpdateSubProcessDefinitionByParent根据父流程更新子流程的定义。
- InitSubInstanceState初始化子实例状态。
- CreateCommand将创建的子流程命令插入数据库中。
这里ProcessInstanceMap并不是jdk包下的map,而是表t_ds_relation_process_instance的数据的。里面存储了父流程实例以及任务的关系的。3到6这些步骤都是crud的业务,里面具体的细节就赘述了。
2.15 CommonTaskProcessor里执行Dispatch Task方法
DispatchTask方法干了三件事情:
- 获取TaskPriorityQueueImpl的bean。
- 将TaskInstance,ProcessInstance封装成TaskPriority。
- 将封装后的TaskPriority放到这bean下的queue中去,这个队列是jdk的PriorityBlockingQueue,是一个具有优先级别的无界阻塞队列。
此时将DispatchTask放进task,那如何消费队列中的task的呢?2.16将说明这个议题。
2.16 TaskPriorityQueueConsumer执行run和dispatchTask方法
TaskPriorityQueueConsumer是一个继承Thread的类。在MasterServer启动之后,根据Spring的特性,TaskPriorityQueueConsumer会创建一个对象由Spring管理。TaskPriority会执行init的方法。线程启动并且设置线程名字Task UpdateConsumerThread。
Run方法中以3(MasterConfig.getMasterDispatch Task ) 次拉取为循环,每次1秒从队列中(BatchDispatch)拉取TaskPriority,如果失败就有重新丢回到这队列中去。
随后对拉取的数据进行DispatchTask方法。
DispatchTask方法中做了三件事情:
- 从TaskPriority中取出context,根据Command,ExecutorType和Workergroup封装成Execution Context。
- 将ExecutionContext交给Executor Dispatcher进行Dispatcher,这将在2.17中说明。
- 如果发送成功,返回result为true。将TaskEvent添加到TaskEventService (addEvents)中,由TaskEventService进行管理的。TaskEventService的说明将在2.19中介绍。
2.17 ExecutorDispatcher里执行Dispatch方法
ExecutorDispatcher这个类就干了三件事情:
- ExecutorDispatcher此类实现了InitializingBean。也就是创建过程中执行了AfterPropertiesSet方法,ExecutorManagers注册了Worker和Client的ExecutorType。
- Dispatch方法中获取到了Worker的ExecutorType,然后进行HostManagar.select。在Select方法中会根据MasterConfig中的Host-selector策略选择机器,默认是Lower-weight。如果读者有自定义的需求,则可以实现HostManager接口的。(Lower-weight如何选择的,就不详细介绍了。因为难度并不大,也就是纯属业务的变化的,有兴趣就可以自行阅读的。)
- 选择完了Host之后,调用ExecutorManager进行execute。这里的EeforeExecute和AfterExecute是没有内容的,如果读者有需求,同样可以在此添加内容的。在2.18中会说明execute的内容。
2.18 NettyExecutorManager执行execute和doExecute方法
ExecutorManager目前就一个实现类,就是NettyExecutorManger。
在init方法中NettyRemotingClient注册了TaskExecuteResponse、TaskExecuteAck和
TaskKillResponse的Processor。这些Processor是用来让Master和Worker进行交互的。
在Executor方法中最核心的方法就是DoExecute。
在DoExecute中NettyRemotingClient根据有效的Host发送Command。如果发送失败了,剔除失败节点,将task重新添加到队列中。
至此,Master就以Command形式发送task信息给Worker,说明一下,此时的Command是Remote包下的Command,与前面的Command没有任何关系的,不要混淆了。Master和Worker的交互过程会在第四章节中讲述。
2.19 TaskEventService执行addEvents方法
先说说TaskEventService创建过程。这是由Spring管理的,然后执行Start方法之后,有两个线程创建出来,一个是TaskEventThread,另外一个是TaskEventHandlerThread。在TaskEventThread会从EventQueue中取出TaskEvent事件进行提交(submitTaskEvent)。而TaskEventHandlerThread会执行EventHandler方法。EventHandler中会从TaskExecuteThreadMap中取出数据来执行executeEvent方法。
那么TaskExecuteThreadMap如何插入数据的呢?答案就是本节所说的addEvents方法。
addEvents方法中会调用TaskExecuteThreadPool中的SubmitTaskEvent方法。而在SubmitTaskEvent方法中最核心的功能就是往TaskExecuteThreadMap放入数据,也就是以ProcessInstanceId为key,TaskExecuteThread为value的map,并且会调用TaskExecuteThrad的addEvent方法,将event放入到events队列中。
至于TaskExecuteThread做了哪些事情将在2.20中说明。
2.20 TaskExecuteThread执行Persist方法
接上文2.19的在TaskExecuteThreadPool中ExecuteEvent方法。
执行TaskExecuteThread中的run方法。在run方法中从events队列中取出TaskEvent,并执行Persist持久化操作的,将task信息保存到数据库中的。
在Persist方法中,重点是Switch结构下的内容。根据DISPATCH,RUNNING,RESULT,执行不同的方法,封装不同的TaskInstance内容保存到数据库中,并发送请求给Worker。
另外构建StateEvent对象,交给WorkerflowExecuteThreadPool进行处理持久化后的StateEvent对象。stateEvent应该如何处理呢?请参考2.22的内容。
2.21 MasterSchedulerService总结
MasterServer的MasterSchedulerService已经基本讲完。回到最开始的MasterServer这部分,发现MasterSchedulerService后面的两个bean没有讲,也就是EventExecuteService以及FailoverExecute Thread.这两个都是线程的,将在2.22和2.23中说明这最后两个bean。
2.22 EventExecuteService线程的run方法
在MasterServer调用Start方法后,EventExeuctor Service的run方法执行过程如下:
- 每100毫秒执行EventHandler方法。
- 每次执行EventHandler方法时,从2.5章节的第3步ProcessInstance ExecCacheManager中取出WorkFlowExecutorThread,通过WorkflowExecuteThreadPool执行ExecuteEvent方法。
- 在ExecuteEvent方法中, 可以发现最核心的方法就是HandlerEvents方法。
- 在HandlerEvents中可以发现,从2.11章节的第9步的StateEvents队列取出StateEvent,然后在通过StateEventHandler方法进行判断的。
- 在WorkflowExecutorThread的stateEventHandler方法中,根据StateEventType的不同,以有6种不同类型的方法去调用,分别为PROCESS_STATE _CHANGE、TASK_STATE_CHANGE、PROCESS_TIMEOUT、TASK_TIMEOUT、TASK_RETRY、PROCESS_BLOCKED。通过不同的type调用不同的方法,如PROCESS_STATE_CHANGE调用ProcessStateChangeHandler方法,这里就不详细讲述各个方法的内容了,其本质上也都是内存数据结构的变化。
P.S.:
- 如果StateEventHandler方法中某一类型成功执行,则从StateEvents队列中移除它了。
- 返回到WorkflowExecuteThreadPool类的ExecuteEvent方法中,执行完第3步之后,会有个回调函数,失败就执行OnFailure方法。成功就执行OnSuccess方法,NotifyProcessChanged通知流程改变中,要么NotifyMyself,要么通知其他流程NotifyProcessChanged的。
2.23 FailoverExecutorThread线程的Run方法
此节为机器故障切换执行的线程,主要干了5件事情。具体执行流程如下:
- Run方法中FailoverService.checkMaster Failover检查是否需要切换的host。
- 如果有host的话,就进入FailoveMaster WithLock方法。在此方法中,从zk中通过分布式锁来进行切换机器,也就是进入FailoverMaster方法。
- 在FailoverMaster中,从ProcessSerivce里(QueryNeedFailover ProcessInstance)查询所需要切换的流程实例(NeedFailover ProcessInstanceList)。
- 接下来,就是通过zk获取有效的WorkerServers.failoverTaskInstance来切换task。在切换task时有三个步骤,分别是:当是Yarnjobs时,则直接杀掉 ; 改变task的状态,也就是从Running到Needfailover ; WorkflowExecutor ThreadPool提交StateEvent。
- 在ProcessService中处理该切换的流程,增加切换流程实例的Command,插入数据库中。
下两章将继续讲述Worker和Master与Worker的交互。
达人专栏 | 还不会用 Apache Dolphinscheduler?大佬用时一个月写出的最全入门教程【三】的更多相关文章
- 【达人专栏】还不会用Apache Dolphinscheduler吗,大佬用时一个月写出的最全入门教学【二】
02 Master启动流程 2.1 MasterServer的启动 在正式开始前,笔者想先鼓励一下大家.我们知道启动Master其实就是启动MasterServer,本质上与其他SpringBoot项 ...
- 我在Apache DolphinScheduler的心路历练
摘要:Apache DolphinScheduler 目前是 Apache 孵化项目,目前正在快速发展中.加入Apache DolphinScheduler社区已一年多,已有 400+ 公司在生产上使 ...
- 金秋十月 - Apache DolphinScheduler 收获 2 位新 Committer
点击上方蓝字关注 Apache DolphinScheduler Apache DolphinScheduler(incubating),简称"DS", 中文名 "海豚调 ...
- 本周六 Apache DolphinScheduler & Doris 将联合线上 Meetup
活动背景 2020年,大数据成为国家基建的一个重要组成,大数据在越来越多的领域展现威力.随着大数据的应用场景越来越多,大家对数据的响应速度和数据加工工作流的方便程度也提出了更高的要求.在这种背景下,相 ...
- Apache DolphinScheduler之最美好的遇见
关于 Apache DolphinScheduler社区 Apache DolphinScheduler(incubator) 于17年在易观数科立项,19年3月开源, 19 年8月进入Apache ...
- 活动回顾|Apache DolphinScheduler x Pulsar 在线 Meetup
关于 Apache DolphinScheduler: " Apache DolphinScheduler(Incubating) 是一个分布式去中心化.易扩展的可视化工作流任务调度系统,致 ...
- Apache DolphinScheduler & Doris 将于本周六联合进行线上 Meetup
01 - 活动介绍 2020年,大数据成为国家基建的一个重要组成,大数据在越来越多的领域展现威力.随着大数据的应用场景越来越多,大家对数据的响应速度和数据加工工作流的方便程度也提出了更高的要求.在这种 ...
- Apache DolphinScheduler 需要的sudo,还可以这么玩,长见识了!
Apache DolphinScheduler(incubator)需要的sudo,还可以这么玩,长见识了! 在新一代大数据任务调度 - Apache DolphinScheduler(以下简称dol ...
- Apache DolphinScheduler新一代分布式工作流任务调度平台实战-上
概述 定义 dolphinscheduler 官网地址 https://dolphinscheduler.apache.org/ dolphinscheduler GitHub地址 https://g ...
随机推荐
- elasticsearch-spark的用法
Hadoop允许Elasticsearch在Spark中以两种方式使用:通过自2.1以来的原生RDD支持,或者通过自2.0以来的Map/Reduce桥接器.从5.0版本开始,elasticsearch ...
- AMS 新闻视频广告的云原生容器化之路
作者 卓晓光,腾讯广告高级开发工程师,负责新闻视频广告整体后台架构设计,有十余年高性能高可用海量后台服务开发和实践经验.目前正带领团队完成云原生技术栈的全面转型. 吴文祺,腾讯广告开发工程师,负责新闻 ...
- CF1588F Jumping Through the Array
在讲正解之前,先播一个小故事: xay 复杂度错误过题.将操作按照时间分块,块内他令所有置换环都必须有至少一个"黑点". 可以通过没有修改 \(p\) 操作,同时 \(p_i=i\ ...
- Vue是怎么渲染template内的标签内容的?
我们在使用Vue做项目时,都会用到脚手架,相应的我们会在template写标签内容.那么你知道为什么会在template写标签吗?这当中经过了怎样的处理呢? <template> < ...
- Python量化-如何获取实时股票信息
如何获取实时股票信息 股票信息的接口有很多,之前大家常用的是新浪的,但在年初的时候,新浪的接口突然不能使用,给大家造成了很大的困扰,为此网上也有很多教程教大家如何从新浪获取数据,跟着教程弄了半天也不行 ...
- VisionPro · C# · 创建项目
将 VisionPro 引入 C# 项目程序中需要执行以下操作: 1.更改项目程序.NET框架: 2.添加编程引用: 3.添加界面设计控件引用: VisionPro 不同版本对应不同的 .NET 框架 ...
- Oracle数据库常用查询语句
1.[oracle@dbserver ~]$ sqlplus / as sysdbaSQL*Plus: Release 11.2.0.4.0 Production on Tue Mar 15 15:1 ...
- 字符输出流_Writer类&FileWriter类介绍和字符输出流的基本使用_写出单个字符到文件
java.io.Writer:字符输出流,是所有字符输出流的最顶层的父类,是一个抽象类 共性的成员方法: - void write(int c) 写入单个字符 - void write(char[] ...
- 要想不踩SaaS那些坑,得先了解“SaaS架构”
摘要:围绕当下许多企业青睐的SaaS应用开发,华为云开发者技术服务工程师程泽在DTT首期带来主题为 <SaaS云原生应用典型架构> 的DTT首期直播分享. 本文分享自华为云社区<DT ...
- mybatis-拦截器实际应用-替换表名-2022新项目
一.业务场景 考虑到新项目中部分与业务数据相关的表在后期数据量会比较大,架构师在最开始设计项目中与业务数据相关的表时,就已经考虑使用分表来 进行处理,给业务数据相关的每张表都添加统一批次的后缀,查询这 ...