Spark Rpc的启动过程(其实也就是集群的启动过程)

来源:互联网 发布:华为相机软件下载 编辑:程序博客网 时间:2024/06/14 18:55


Spark RPC在2.0之后是完全基于Netty实现的RPC,主要核心组件有: RpcEnv、RpcEnvFactory、RpcEndpoint、RpcEndPointRef(对应到Netty的实现就是NettyRpcEnv、NettyRpcEnvFactory、NettyRpcEndpoint、NettyRpcEndPointRef)。当然还有一些其他组件,我们这里不涉及了,关于底层传输后期在补充。


概念讲解:

RpcEnv:其实就是一个RPC的环境,RpcEndponit需要使用一个名字注册到RpcEnv中,目的是接受Rpc消息并处理,同时也支持消息的发送。异常处理和RpcEndPointRef的检索。

RpcEnvFactory:RpcEnv的创建工厂

RpcEndpoint:一个Rpc客户端,负责处理消息,有声明周期方法Onstart->receive->Onstop

RpcEndPointRef:如果在本节点被创建表示自己的一个ref,否则表示一个远程节点的ref


启动过程:

接下来我们以Master的启动来说明Rpc的启动过程,当我们使用start-all.sh启动集群时候,无非是以java命令行的方式启动Master和Worker而已(当然还有ssh到其他节点的过程)。

所以最后就是转换为Master、Worker的main方法执行过程,接下来我们就看一下Master的启动流程:

Master的main方法:

 def main(argStrings: Array[String]) {    Utils.initDaemon(log)    val conf = new SparkConf    val args = new MasterArguments(argStrings, conf)    //(rpcEnv,WebUi,RestServerPort)    val (rpcEnv, _, _) = startRpcEnvAndEndpoint(args.host, args.port, args.webUiPort, conf)    rpcEnv.awaitTermination()  } 
主要完成两件事:1、是参数的解析 2、启动RpcEnv和注册Master。接下来就分析一下启动RpcEnv和注册Master的流程。通过调用startRpcEnvAndEndpoint方法传入master的主机地址,端口号,webui以及配置信息。接下来看一下startRpcEnvAndEndpoint方法实现:

  /**    * Start the Master and return a three tuple of:    * (1) The Master RpcEnv    * (2) The web UI bound port    * (3) The REST server bound port, if any    */  def startRpcEnvAndEndpoint(                              host: String,                              port: Int,                              webUiPort: Int,                              conf: SparkConf): (RpcEnv, Int, Option[Int]) = {    val securityMgr = new SecurityManager(conf)    //创建一个RpcEnv环境,此处返回的是NettyRpcEnv    val rpcEnv = RpcEnv.create(SYSTEM_NAME, host, port, conf, securityMgr)    //Endpoint类似于Akka的Actor,注册Master到RpcEnv    val masterEndpoint = rpcEnv.setupEndpoint(ENDPOINT_NAME, new Master(rpcEnv, rpcEnv.address, webUiPort, securityMgr, conf))    val portsResponse = masterEndpoint.askWithRetry[BoundPortsResponse](BoundPortsRequest)    (rpcEnv, portsResponse.webUIPort, portsResponse.restPort)  }}
这里面的重点是:1、为Master创建RpcEnv,2:将Master注册到RpcEnv中。(注意:这里面的RpcEnv是Master的RpcEnv,后面创建Worker时候,Worker有自己的RpcEnv)。

最后通过执行setupEndpoint方法注册:

  override def setupEndpoint(name: String, endpoint: RpcEndpoint): RpcEndpointRef = {    dispatcher.registerRpcEndpoint(name, endpoint)  }

dispatcher:是一个消息调度器,负责消息路由到对应节点(里面主要存储着name和EndPointData的对应关系)。dispatcher的注册方法其实就是将RpcEndPoint的name和对应的RpcEndPoint对应存储起来。最后返回当前注册的EndPoint的一个ref引用。具体见如下方法:

 def registerRpcEndpoint(name: String, endpoint: RpcEndpoint): NettyRpcEndpointRef = {    //获取的是RpcEnv的地址    val addr = RpcEndpointAddress(nettyEnv.address, name)    val endpointRef = new NettyRpcEndpointRef(nettyEnv.conf, addr, nettyEnv)    synchronized {      if (stopped) {        throw new IllegalStateException("RpcEnv has been stopped")      }      if (endpoints.putIfAbsent(name, new EndpointData(name, endpoint, endpointRef)) != null) {        throw new IllegalArgumentException(s"There is already an RpcEndpoint called $name")      }      val data = endpoints.get(name) //类型:EndpointData      endpointRefs.put(data.endpoint, data.ref)      receivers.offer(data) // for the OnStart message    }    endpointRef  }

如上就是Saprk Rpc的启动过程,Saprk Rpc的启动就是在Master和Worker的启动过程中启动的。








原创粉丝点击