03
Worker启动流程
3.1
WorkerServer启动
WorkerServer启动跟MasterServer启动一样,都是Springboot应用的,而且相比与Master而言会简单许多,因为只是执行task,不需要划分DAG等,只需要接收Netty请求执行而已。
WorkerServer的main函数启动之后,运行run方法,会干以下4个事情。
初始化NettyRemotingServer,这个跟MasterServer一样都会注册很多个Processor,Master和Worker的交互的Processor在第4章节说明。不过这里有个Processor值得着重强调一下,就是TaskExecuteProcessor,将在3.3章节中说明。
WorkerRegistryClient向zk注册以及移除节点,原理完全跟MasterRegistryClient一样,也会开启一个心跳线程的,具体参考2.2章节内容的。
WorkerManagerThread启动,从Worker ExecuteQueue中取出数据,TaskExecute Thread来执行task的,此队列如何插入数据参考3.3章节。
RetryReportTasksStatsThread的启动,就是每5分钟将缓存里的Running和Result的信息发送给Master。
3.2
TaskPluginManager的installPlugin方法
首先说一下,TaskPluginManager是Service模块里的,并不是Worker模块下的。那为什么会在这里提这个类呢?理由很简单,就是加载task是使用了Java的SPI机制的。InstallPlugin是加载了task模块下的所有task放到内存中,Worker接收到Master发送的task信息,执行相对应的task。例如task的名字是SPARK,则执行SparkTask,task名字是FLINK,则执行FlinkTask。如果读者想扩展所需要的task信息,只需要参考下面链接即可。
https://mp.weixin.qq.com/s/nmbazSl-UW4SMivbS6E_6Q
3.3
TaskExecutorProcessor里执行Process方法
Master发送Command消息的在Worker模块一定会先经过这Process方法,至于为什么会经过这Process方法,将在第4.5章节说明。本节说这Process干了的4件事情。
校验并且转换成taskExecute RequestCommand,获得里面的tastExecutionContext。
检查操作用户是否存在以及获得执行的本地路径。
如果task需要延后时间,则(sendTaskExecuteDelayCommand)发送延后时间的请求方法给Master。
在WorkerManager中offer一条线程TaskExecuteThread。而TaskExecuteThread也是Worker的核心线程。
这个线程执行的内容将在3.4中说明。
3.4
TaskExecuteThread里执行run方法
在2.20中也有个TaskExecuteThread,不过这个是Master模块下,主要负责task的持久化操作,跟本节所说的Worker模块下的TaskExecuteThread没有关系,仅仅名字相同而已。
WorkerManagerThread中会构建一个固定的后台线程池,名字为Worker-Execute-Thread。里面共有100(WorkerConfig.getExecThreads)个线程。3.3中offer的线程就是到这个线程池里面的。线程Run方法主要干了下面7件事情:
检查用户或者租户是否存在。
改变运行状态,启动running状态,并且(sendTaskExecuteRunningCommand)发送运行状态给Master。
下载hdfs或者local文件(downloadResource)。
构建自定义参数(preBuildBusinessParam)。
通过taskPluginManager(spi机制)以及taskExecutionContext里的taskType获取相对应的taskChannel,并且根据taskChannel创建相对应的task。
初始化task->加载props->handle(执行具体task内容)->如果需要发送警告, 则发送alert。
最后,taskCallService发送响应给Master,并且清空task执行路径(clearTaskExecPath)。
下面以FlinkTask举例。在第6步中会加载FlinkTaskChannel,createTask创建出FlinkTask。在FlinkTask中,init方法会加载FlinkParams,SetMainJarHome以及SetMainArgs。在抽象类AbstrackYarnTask会执行handle方法(因为FlinkTask继承了AbstractYarnTask)。在handle方法中会BuildCommand 构建一条Shell命令的,由ShellCommandExecutor的父类Abstract Command Executor的run方法执行,封装TaskResponse并返回。具体如下图。
04
Master和Worker的交互流程
4.1
Netty简单介绍
第2章节和第3章节分别讲述了Master和Worker的启动过程的,本章节将讲述了Master和Worker如何通过Netty进行交互和处理消息的。Netty的demo就参考网上就好了。
本节只介绍使用Netty的server和client的API的相互交换过程的。里面具体的细节包括线程处理,网络传输等,可能需要参考专门的Netty资料的。
Netty的server和client的只考虑到的API的相互过程就会很简单。启动完Server和Client之后,Client会将传递的内容在固定的端口号下给WriteAndFlush方法。Server也在同样的端口号下ChannelRead读Client传递过来的内容的。读完之后也WriteAndFlush方法,Client也在ChannelRead读Server传递过来的内容。就这样如此反复。理解这个过程会对下面的流程很有帮助。如图所示:
4.2
Master 和 Worker 的 Cetty Remoting Server
在2.1节讲述MasterServer的时候有一类全是Processor的内容的,但在剩下的第二章节的内容都没有讲述这些Processor,因为这些Processor都是跟Worker进行交互作用的。在本章节讲述这些Processor的。
在MasterServer和WorkerServer都会启动NettyRemotingServer。
在MasterServer的NettyRemotingServer监听的端口号为5678,接收到Worker发送的信息,交给Master注册的Processor处理。
在WorkerServer的NettyRemotingServer监听的端口号为1234,接收到Master发送的消息,交给Worker注册的Processor处理。
至此Master和Worker服务端构建完成,接下来就是客户端的内容的。
4.3
Master下封装交互的Command
回到2.18节,在Master模块下,NettyExecutorManager的DoExecute方法中,有一行代码就是NettyRemotingClient.send(host,command)。在第二章节讲到这里就没讲了。因为从这里开始就是Master和Worker的交互过程了。本节将重点讲述Send方法参数command。
在2.16节TaskPriorityQueueConsumer干的第一件事情就是封装ExecutionContext,封装过程中有个ToCommand方法,会到这个Consumer类的ToCommand方法里,在ToCommand方法里中会进入到TaskExecuteRequestCommand类的Convert2Command方法里。而在这个Convert2Command里中构建Command,其中Command的Type为TASK_EXECUTE_REQUEST。这个Type极为重要,在交互过程中就是通过这个Type去找Processor的。
4.4
NettyRemotingClient里执行Send方法
在4.3节中讲了NettyRemotingClient的Command的参数,本节将讲述Send方法的。首先说明一下,NettyRemotingClient是Remote模块下的,换句话说Master和Worker都会用到这个Remote模块的。具体执行如下图所示。Connect就会连接Worker的IP和1234端口的。
4.5
NettyServerHandler里执行ChannelRead方法
如同4.1所说,NettyClient将Command数据writeAndFlush之后,NettyServer就会channelRead出来。注意本章节说的是
remote模块的org.apache.dolphinscheduler .remote.handler包下NettyServerHandler类。
不是remote模块的org.apache.dolphinscheduler .rpc.remote包下NettyServerHandler类
ChannelRead方法下面执行是ProcessRecieved方法。
在ProcessReceived方法下,会根据前面传过来的CommandType来获取相对应的NettyRequestProcessor。在4.3节中会根据TASK_EXECUTE_REQUEST去找到TaskExecutorProcessor 类。
执行TaskExecutorProcessor里面的Process方法,这就解释了3.3章节开头说的一定会经过TaskExecutorProcessor这个类的了。
4.6中有一张图详解Master和Worker的交互过程Master和Worker使用的Netty的内容都在remote模块,只是处理的模块不同,走的不同的是Processor而已。上面讲述了Master使用Netty的内容发送给Worker,而Worker发送消息给Master的话基本如出一辙。关于此,请读者自行研究了。
Master和Worker之间有很多Processor交互的,例如Master模块TaskKillResponseProcessor和taskEventProcessor等,Worker模块下的 HostUpdateProcessor以及TaskKillProcessor等,当看懂下面的这幅图的时候,这些Processor就不难理解的了。就请读者自行阅读的了。
参与贡献
随着国内开源的迅猛崛起,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%22volunteer+wanted%22
如何参与贡献链接:https://dolphinscheduler.apache.org/zh-cn/docs/development/contribute.html
来吧,DolphinScheduler开源社区需要您的参与,为中国开源崛起添砖加瓦吧,哪怕只是小小的一块瓦,汇聚起来的力量也是巨大的。
参与开源可以近距离与各路高手切磋,迅速提升自己的技能,如果您想参与贡献,我们有个贡献者种子孵化群,可以添加社区小助手微信(Leonard-ds) ,手把手教会您( 贡献者不分水平高低,有问必答,关键是有一颗愿意贡献的心 )。
添加小助手微信时请说明想参与贡献。
来吧,开源社区非常期待您的参与。
活动推荐
2022年6月18日,Apache DolphinScheduler社区联合TiDB社区共同举办的Meetup即将重磅开启!我们也有幸邀请到了来自阿里云、国内跨境电商巨头SHEIN、TiDB社区等企业的资深大数据工程师与开发者,从数据库、数据调度、应用开发、技术外延等话题探讨在两个开源项目的开发实践。
本次活动受疫情影响仍以线上直播的形式开展,活动现已开放免费报名,欢迎扫描下图二维码,或点击“阅读原文”免费报名!
扫码观看直播
扫码入直播群
更多精彩推荐
☞恭喜!Apache DolphinScheduler社区再添9枚“新鲜”Committer
☞达人专栏 | 还不会用 Apache Dolphinscheduler?大佬用时一个月写出的最全入门教程【二】
☞Apache Dolphinscheduler 5月Meetup:6个月重构大数据平台,帮你避开调度升级改造/集群迁移踩过的坑
☞金融任务实例实时、离线跑批,Apache DolphinScheduler 在新网银行的三大应用场景与五大优化
☞中国联通改造 Apache DolphinScheduler 资源中心,实现计费环境跨集群调用与数据脚本一站式访问
我知道你在看哟