Master
对于Master,其启动脚本就是通过java mainClass的方式调用main方法启动Master的java进程。
自然调用的就是org.apache.spark.deploy.master.Master的main方法。
于是就从org.apache.spark.deploy.master.Master中的main方法开始看起
1.Master#main
new SparkConf
Spark应用程序的配置,将spark的各种参数设置为键值对 ;
new MasterArguments(argStrings, conf)
解析命令行中的参数,例如--host,--port,--webui-port等,当然不指定也是有默认值的
startRpcEnvAndEndpoint
创建rpc通信环境和启动通信终端
rpcEnv.awaitTermination()
阻塞程序直到RpcEnv退出
2.MasterArguments#parse
那么我们在运行Spark源码的Master时,可以如下在运行配置中添加--host 192.168.10.1 --port 7077 --webui-port 8080,当然其实不加也可以运行,因为这种参数其实一般都有默认值的,8080就其运行后我们浏览器web界面的访问端口,而7077就是内部通信端口,比如后面讲到的Worker注册到Master上就是用7077端口,至于host就是主机ip。
3.Master#startRpcEnvAndEndpoint
new SecurityManager(conf)
安全相关的,不多赘述
RpcEnv.create
创建RpcEnv,名字sparkMaster
rpcEnv.setupEndpoint
注册一个通信终端,名字为Master,启动发现参数里new了一个Master
masterEndpoint.askSync
RpcEndpointRef以同步的方式发送消息BoundPortsRequest给Master,等待其接受消息并返回结果。
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
启动Master服务
6.NettyRpcEnv#startServer
transportContext.createServer
创建TransportServer
dispatcher.registerRpcEndpoint
在dispatcher上注册RpcEndpointVerifier
7.Utils#startServiceOnPort
先对startPort进行参数校验,然后尝试maxRetries次启动服务,如果超过maxRetries次仍然没启动成功,那么就排抛出异常
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方法), 由于Master是继承ThreadSafeRpcEndpoint,而ThreadSafeRpcEndpoint实现了特质RpcEndpoint,类似于Java中的接口,也就是说会调用Master中的onStart方法
10.Master#onStart
这函数比较长,所以就挑重点说 ,首先是打印日志,其实看源码的时候日志非常重要,有时候一个函数只需要看起打印的英文日志就知道大概意思了。
与选举有关
点击electedLeader
11.Master#electedLeader
很明显发送了一个无需应答的消息ElectedLeader
既然有发送,那么就必要接受,所以,直接看
12.Master#receive
被选取为laeder,状态被置为ALIVE,打印日志
最终结果
运行起来之后,可以访问http://localhost:8080/ ,看到其Web界面