Spark3.0.3-Worker的启动流程源码分析

Worker

对于Master,其启动脚本就是通过java mainClass的方式调用main方法启动Worker的java进程。

自然调用的就是org.apache.spark.deploy.worker.Worker的main方法。

于是就从org.apache.spark.deploy.worker.Worker中的main方法开始看起。

1.Worker#main

new SparkConf

Spark应用程序的配置,将spark的各种参数设置为键值对 ;

new WorkerArguments

解析命令行中的参数,例如--webui-port以及masterUrl等,其实端口号和主机这些一般不指定也是有默认值的,注意这里的masterUrl必须指定,不然运行报错

startRpcEnvAndEndpoint

创建rpc通信环境和启动通信终端

rpcEnv.awaitTermination()

阻塞程序直到RpcEnv退出

2.WorkerArguments#parse

这个函数的大部分和上一次分析的Master的启动的MasterArguments中的parse差不多,不过需要注意的不同点如上图,会解析命令行中的MasterUrl,因为Worker是要注册到Master上的。

点击parseStandaloneMasterUrls进入

发现就是我们输入的masterUrl必须以spark://为前缀,所以我在运行源码中的Worker是需要加上如下参数,其中192.168.10.1是本机ip,7077是与Master的通信端口。

 3.Worker#startRpcEnvAndEndpoint

new SecurityManager

安全相关的,不多赘述

RpcEnv.create

创建RpcEnv,名字sparkWorker

masterUrls.map(RpcAddress.fromSparkURL)

获取master的地址

rpcEnv.setupEndpoint

注册一个通信终端,名字为Worker,启动发现参数里new了一个Worker

4.RpcEnv#create->RpcEnv#create

至于标题为什么这么写,就是源码经常有的一种套娃现象,点击进入create函数,发现里面又调用了一个create(这里用了函数重载)。

RpcEnvConfig

构建RpcEnvConfig

new NettyRpcEnvFactory().create(config)

这用到了设计模式中的工厂模式,单纯看命名就知道是用NettyRpcEnvFactory创建NettyRpcEnv,一般情况xx工厂就是用来创建xx的。

 5.NettyRpcEnv#create

 new NettyRpcEnv

创建NettyRpcEnv对象

!config.clientMode

判断配置中是否是客户端模式,不是则继续运行if中语句。

nettyEnv.startServer

创建一个将尝试绑定到特定主机和端口的Transport服务。

startServiceOnPort

启动Workerr服务

6.NettyRpcEnv#startServer

 transportContext.createServer

创建TransportServer

dispatcher.registerRpcEndpoint

在dispatcher上注册RpcEndpointVerifier

7.Utils#startServiceOnPort

先对startPort进行参数校验,然后尝试maxRetries次启动服务,如果超过maxRetries次仍然没启动成功,那么就抛出异常

成功后也会打印sparkWorker成功启动日志

8.NettyRpcEnv#setupEndpoint->Dispatcher#registerRpcEndpoint

 new NettyRpcEndpointRef

创建NettyRpcEndpointRef,它是RpcEndpoint的引用,一般用于发消息。

sharedLoop.register

匹配是否是使用专用线程池来传递消息,不是的话就执行这一步

9.MessageLoop#register

 new Inbox

创建一个收件箱,此时会把OnStart消息放入收件箱中

setActive(inbox)

激活收件箱去处理onStart消息

 此时收件箱有一个onStart消息(一旦RpcEndpoint注册到RpcEnv上,就会向inbox队列中加入onStart,处理该消息就会调用RpcEndpoint的onStart方法), 由于Worker是继承ThreadSafeRpcEndpoint,而ThreadSafeRpcEndpoint实现了特质RpcEndpoint,类似于Java中的接口,也就是说会调用Worker中的onStart方法。

10.Worker#onStart

 首先是几个日志打印,我个人认为看源码日志很重要 

createWorkDir()

创建worker的工作目录

new WorkerWebUI-》webUi.bind()

构建worker的web界面并绑定,启动绑定后会打印如下日志

 registerWithMaster()

向Master进行注册

metricsSystem.start()

启动metricsSystem

11.Worker#registerWithMaster

注册Worker到Master上

12.Worker#tryRegisterAllMasters

 masterRpcAddresses.map-》registerMasterThreadPool.submit

遍历masterRpcAddresses,每个masterRpcAddresses都启动一个新线程提交到线程池中。

rpcEnv.setupEndpointRef-》sendRegisterMessageToMaster(masterEndpoint)

之前也说过RpcEndpointRef是RpcEndpoint的引用,一般用于发消息,这里就是发送注册消息给masterRpcEndpoint

 13.Worker#sendRegisterMessageToMaster

 使用send方法发送RegisterWorker消息给master,send方法是不需要回复的,所以直接看Master的receive方法

14.Master#receive

 logInfo("Registering worker %s:%d with %d cores, %s RAM".format(
  workerHost, workerPort, cores, Utils.megabytesToString(memory)))

首先是Master端打印日志

一般情况下,走最后一个else

new WorkerInfo

创建WorkerInfo

registerWorker(worker)

尝试将worker注册到Master上

workerRef.send

注册成功后,发送RegisteredWorker信息给当前要注册的worker,表示已经注册了该Worker了

schedule()

一个调度方法。在等待的应用程序中调度当前可用的资源。每当一个新的应用程序加入或资源可用性改变时(比如对集群资源的变更,节点状态的改变,任务的提交等等),这个方法将被调用。

 15.Master#registerWorker

filter-》workers -= w

在同一个节点上可能会有一个或多个指向该状态为DEAD的worker的引用,删除它们。

removeWorker-》workers += worker

判断Master中有没有与当前注册Worker地址相同且状态为UNKNOWN的,状态为UNKNOWN的worker代表该worker在恢复期间被重启。此时old Worker一定死了,我们就把期初它并接受new Worker。

 16.Worker#receive

 点击handleRegisterResponse进入

之间就说过Master发送RegisteredWorker信息给当前要注册的worker,收到消息匹配后,

打印成功注册到Master的日志

self.send(SendHeartbeat)

Worker给自己发一个SendHeartbeat消息,一看就是与心跳有关的。需要看Worker的

receive函数 

17.Worker#receive

发送心跳信息给Master

仍然是通过send方法发送 ,可以直接去看Master的receive方法

18.Master#receive

 workerInfo.lastHeartbeat = System.currentTimeMillis()

更新注册在Master上的workerInfo中的上次心跳为当前时间

结果

运行起来后,我们访问http://localhost:8081/,可以看到如下worker的web界面:

然后我们又发现之间的Master的web界面出现了注册的worker的信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值