Spark源码解析系列(三、client的注册)

回顾

上一节我们讲了SparkContext构造函数做的初始化,会创建TaskScheduler和DAGScheduler两个重要对象,TaskScheduler又会通过StandaloneSchedulerBackend构建Driver和client。这节我们接着看下client是如何进行注册的。

 client = new StandaloneAppClient(sc.env.rpcEnv, masters, appDesc, this, conf)
 client.start()

创建client

我们进入start()可以看到一个ClientEndpoint,会创建一个内部类ClientEndpoint,里面有个onStart()方法,里面就是和注册有关的内容。

    endpoint.set(rpcEnv.setupEndpoint("AppClient", new ClientEndpoint(rpcEnv)))

调用onStart()

不过调用的过程也是有点绕,看的时候本人也是通过onStart()反推回去的。有兴趣的也可以和我一起过一遍。需要从rpcEnv.setupEndpoint(…)开始,spark1.6之后的网络传输使用netty替代了akka,这个方法的实现类也有所体现NettyRpcEnv。

dispatcher.registerRpcEndpoint(name, endpoint)

看方法名也知道和注册有关,dispatcher做的最重要的事就是创建EndpointData

if (endpoints.putIfAbsent(name, new EndpointData(name, endpoint, endpointRef)) != null) 

我们看到EndpointData构造函数里就做了一件事,创建一个Inbox,所以还要往下看。

// Inbox为[[RpcEndpoint]]存储消息并以线程安全的方式向其发送消息的收件箱。
val inbox = new Inbox(ref, endpoint)

在构造方法里,终于我们看到一个比较熟悉点的名字了OnStart,messages添加了这条消息,看解析我就能清楚这条OnStart类型的信息将会被第一个处理

// OnStart should be the first message to process
  inbox.synchronized {
    messages.add(OnStart)
  }

继续往下看会发现一个process(…)方法处理各种消息,而dispatcher中有个异步线程会不断调用process()处理这些消息。

  def process(dispatcher: Dispatcher): Unit = {
	...
	case OnStart =>
				// client中的onStart()就是在这里被调用
	            endpoint.onStart()

注册application

让我们回到ClientEndpoint的onStart(),调用了registerWithMaster()方法。

registerMasterFutures.set(tryRegisterAllMasters())

以异步方式向所有主机注册,并返回一个JFuture数组。

private def tryRegisterAllMasters(): Array[JFuture[_]] = {
      for (masterAddress <- masterRpcAddresses) yield {
      // 发往线程池异步提交这个任务
        registerMasterThreadPool.submit(new Runnable {
          override def run(): Unit = try {
            if (registered.get) {
              return
            }
            logInfo("Connecting to master " + masterAddress.toSparkURL + "...")
            val masterRef = rpcEnv.setupEndpointRef(masterAddress, Master.ENDPOINT_NAME)
            // 发送application注册消息
            masterRef.send(RegisterApplication(appDescription, self))
          } catch {
            case ie: InterruptedException => // Cancelled
            case NonFatal(e) => logWarning(s"Failed to connect to master $masterAddress", e)
          }
        })
      }
    }

可以看出spark内部组件的交互主要就是通过各种类型消息进行的,client注册完成,master收到消息后,就会进行相关的资源分配,也就是Master的receive()方法有关的处理。
不足之处还望大家指正。下节我们再来分析里面的具体操作,也就算spark的资源分配。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值