spark core源码分析4 worker启动流程

源码位置:org.apache.spark.deploy.worker.Worker.scala

首先查看worker的main方法,与master类似,创建sparkConf,参数解析,以及构造worker对象并创建ActorRef用于对外或者本身的信息交互。这里masters参数可以设置多个

[java]  view plain  copy
  1. def main(argStrings: Array[String]) {  
  2.   SignalLogger.register(log)  
  3.   val conf = new SparkConf  
  4.   val args = new WorkerArguments(argStrings, conf)  
  5.   val (actorSystem, _) = startSystemAndActor(args.host, args.port, args.webUiPort, args.cores,  
  6.     args.memory, args.masters, args.workDir)  
  7.   actorSystem.awaitTermination()  
  8. }  

程序起来后,同样是先执行akka 的preStart方法
 
 
[java] view plain copy
  1. override def preStart() {  
  2.   assert(!registered)  
  3.   logInfo("Starting Spark worker %s:%d with %d cores, %s RAM".format(  
  4.     host, port, cores, Utils.megabytesToString(memory)))  
  5.   logInfo(s"Running Spark version ${org.apache.spark.SPARK_VERSION}")  
  6.   logInfo("Spark home: " + sparkHome)  
  7.   createWorkDir()//创建worker内部工作目录  
  8.   //订阅akka生命周期事件  
  9.   context.system.eventStream.subscribe(self, classOf[RemotingLifecycleEvent])  
  10.   //是否额外的启动一个shuffle服务,确保被executor所读写的shuffle文件在executor退出后被保存,可配  
  11.   shuffleService.startIfEnabled()  
  12.   webUi = new WorkerWebUI(this, workDir, webUiPort)  
  13.   webUi.bind()  
  14.   registerWithMaster()//最重要的动作了,见下面  
  15.   
  16.   metricsSystem.registerSource(workerSource)  
  17.   metricsSystem.start()  
  18.   // Attach the worker metrics servlet handler to the web ui after the metrics system is started.  
  19.   metricsSystem.getServletHandlers.foreach(webUi.attachHandler)  
  20. }  
向Master注册自己
 
 
[java] view plain copy
  1. private def registerWithMaster() {  
  2.   // DisassociatedEvent may be triggered multiple times, so don't attempt registration  
  3.   // if there are outstanding registration attempts scheduled.  
  4.   registrationRetryTimer match {  
  5.     case None =>  
  6.       registered = false  
  7.       //这里向所有的master actorRef发送RegisterWorker消息,上几节有讲master收到该消息后,如果成功处理会反馈RegisteredWorker消息,不成功会发送RegisterWorkerFailed消息  
  8.       tryRegisterAllMasters()  
  9.       connectionAttemptCount = 0  
  10.       //这里在一定时间之后会进入ReregisterWithMaster,里面会判断是否已注册,如果没有会再次发送注册信息。这个是否注册的状态是由master反馈回来的  
  11.       registrationRetryTimer = Some {  
  12.         context.system.scheduler.schedule(INITIAL_REGISTRATION_RETRY_INTERVAL,  
  13.           INITIAL_REGISTRATION_RETRY_INTERVAL, self, ReregisterWithMaster)  
  14.       }  
  15.     case Some(_) =>  
  16.       logInfo("Not spawning another attempt to register with the master, since there is an" +  
  17.         " attempt scheduled already.")  
  18.   }  
  19. }  
看worker收到master的RegisteredWorker消息会怎么做?这里要说一点,worker要注册时并不知道哪台是主,哪台是备,所以向所有配置的master都发送注册信息。主备都收到worker的注册信息之后,只有主才会反馈,并带上自己的masterUrl信息,worker以此来认定主master的actorRef用于真正的信息交互
worker要通过心跳来保持与master的时刻连通,所以注册成功之后,有一个connected标记是否连接正常,在changeMaster方法内部设置connected = true
  
  
[java] view plain copy
  1. <pre name="code" class="java">case RegisteredWorker(masterUrl, masterWebUiUrl) =>  
  2.   logInfo("Successfully registered with master " + masterUrl)  
  3.   registered = true //状态设置为已注册,不然的话,一定时间过后,会发起ReregisterWithMaster而重复注册  
  4.   changeMaster(masterUrl, masterWebUiUrl)//这里是将主master的信息保存  
  5.   
  6.   //在注册成功之后,才开启定时器向master发送心跳  
  7.   context.system.scheduler.schedule(0 millis, HEARTBEAT_MILLIS millis, self, SendHeartbeat)  
  8.   //定时器清理workDir下很久都没有更新的且app也不在执行状态的目录  
  9.   if (CLEANUP_ENABLED) {  
  10.     logInfo(s"Worker cleanup enabled; old application directories will be deleted in: $workDir")  
  11.     context.system.scheduler.schedule(CLEANUP_INTERVAL_MILLIS millis,  
  12.       CLEANUP_INTERVAL_MILLIS millis, self, WorkDirCleanup)  
  13.   }  
如果收到RegisterWorkerFailed消息,则退出
 
 
下面看master接受到worker的心跳之后如何处理
由于worker注册时,master已经将workerId存入idToWorker中,所以这里走Some分支。很简单,只是更新该worker的一个时间戳。这里有必要说明一下None分支,在注册消息到达后,在master 的idToWorker和workers中都会保存,但是当master检测到worker超时时,将worker从idToWorker中删除,这样新的任务就选不了该worker了,但不删除workers中的。workers中的只会在间隔很长一段时间之后仍然没有心跳上来,才说明该worker真正无法再工作了,再从workers中删除。这里的None分支就是应对超时过后,心跳又继续上来了,就向worker发送重新注册的消息ReconnectWorker

 
 
[java] view plain copy
  1. case Heartbeat(workerId) => {  
  2.   idToWorker.get(workerId) match {  
  3.     case Some(workerInfo) =>  
  4.       workerInfo.lastHeartbeat = System.currentTimeMillis()  
  5.     case None =>  
  6.       if (workers.map(_.id).contains(workerId)) {  
  7.         logWarning(s"Got heartbeat from unregistered worker $workerId." +  
  8.           " Asking it to re-register.")  
  9.         sender ! ReconnectWorker(masterUrl)  
  10.       } else {  
  11.         logWarning(s"Got heartbeat from unregistered worker $workerId." +  
  12.           " This worker was never registered, so ignoring the heartbeat.")  
  13.       }  
  14.   }  
  15. }  

至此,worker启动流程以及主动发送的消息介绍完了,剩下的都是被动接收并处理的流程,在之后结合具体job介绍。。。

转载:http://blog.csdn.net/yueqian_zhu/article/details/47976127

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值