Spark-2.4.0 源码学习系列《Master的启动过程》

目录

一、Master启动主流程

1.1 Master main方法    

1.2 startRpcEnvAndEndpoint(...)

1.3 rpcEnv.setupEndpoint(...)

二、Master启动需要注意的地方

2.1 Dispatcher的线程池

2.2 Inbox.process(...)

三、Master的初始化过程

3.1 参数初始化

3.2 Master的onStart()方法 


一、Master启动主流程

1.1 Master main方法    

    执行 $SPARK_HOME/sbin/start_master.sh 脚本时,执行的是Master.scala中的main方法。下面我们来看代码,看Master启动过程中都干了哪些事:

1.2 startRpcEnvAndEndpoint(...)

    截图中有注释,我就不一一说了。我们看重点:startRpcEnvAndEndpoint(...)

1.3 rpcEnv.setupEndpoint(...)

    这里我们重点看一下第3步: val masterEndpoint = rpcEnv.setupEndpoint(...)

    这个方法需要两个参数:endPoint的名字,这里是ENDPOINT_NAME,也就是“Master”,还有一个endPoint对象,也就是Master对象,Master对象就是在此处实例化 的(稍后讲解)。

    rpcEnv.setupEndpoint(...)最终调用的是dispatcher.registerRpcEndpoint(name, endpoint),我们来看一下这个方法:

        这里第4步和第7步需要强调一下:

        第4步:向Dispatcher中注册EndPoint时,需要传入一个EndPointData,初始化EndPointData时会创建该EndPoint的Inbox,而InBox的初始化完成后,会向InBox的messages中添加一个OnStart信息(OnStart是InBox处理的第一条信息)。

 org/apache/spark/rpc/netty/Inbox.scala:80

      第7步:向Dispatcher的receviers中添加一个EndPointData,这个data是为OnStart准备的。

    rpcEnv.setupEndpoint(...)方法执行完后,返回一个endpointRef,Master.scala中的启动相关的代码就看完了(Master初始化还没看),在看Master对象初始化之前我们先回头看一下Dispatcher。

二、Master启动需要注意的地方

2.1 Dispatcher的线程池

            还记得Dispatcher的线程池吗?这里我们再来看一下:

2.2 Inbox.process(...)

    Dispatcher初始化了一个线程池,并启动。我们在看一下MessageLoop

    Master的注册过程中向dispatcher的receivers中添加了一个EndPointData,Inbox中添加了一个OnStart。所以线程运行到if(data == PoisonPill)时,条件不成立,进入第3步,执行data.inbox.process(Dispatcher.this)。我们再来看看这个方法:

     首先取出inbox中的数据,做非空判断,处理线程数问题。下面开始处理数据:

   我们看一下3.3 OnStart信息的处理。InBox初始化时往messages中添加了一个OnStart,所以Master第一次启动时,Dispatcher-EndPoint-InBox中存的第一条信息是OnStart。3.2.1调用的onstart()方法即是Master的onStart方法。也就是说,在Master初始化完成后,便开始执行其onStart()方法。

三、Master的初始化过程

    下面我们看一下Master的初始化过程,随后再看下Master的onStart()方法都干了哪些事:

    Master是在Master.scala startRpcEnvAndEndpoint(...)方法中向env注册时通过new关键字初始化的。我们直接看Master类有哪些属性,之后再看其onStart方法。

3.1 参数初始化

    Master初始化时初始化了很多属性,这里我们捡几个重要的列一下:

  // hadoop配置
  private val hadoopConf = SparkHadoopUtil.get.newConfiguration(conf)
  // Worker超时时间,默认60s
  private val WORKER_TIMEOUT_MS = conf.getLong("spark.worker.timeout", 60) * 1000
  // executor最大重试次数(默认10次,也就是说最多执行11次)
  private val MAX_EXECUTOR_RETRIES = conf.getInt("spark.deploy.maxExecutorRetries", 10)
  // worker列表,里面存放worker的id,地址,端口,核心数,内存,worker引用,webUi地址
  val workers = new HashSet[WorkerInfo]
  // 等待中的apps(已提交未处理)
  private val waitingApps = new ArrayBuffer[ApplicationInfo]
  // app列表
  val apps = new HashSet[ApplicationInfo]
  // 处理完成的apps
  private val completedApps = new ArrayBuffer[ApplicationInfo]
  // 下一个App编号
  private var nextAppNumber = 0
  // 驱动
  private val drivers = new HashSet[DriverInfo]
  // 已完成的driver
  private val completedDrivers = new ArrayBuffer[DriverInfo]
  // Drivers currently spooled for scheduling
  private val waitingDrivers = new ArrayBuffer[DriverInfo]
  // 下一个驱动的编号
  private var nextDriverNumber = 0
  // After onStart, webUi will be set
  private var webUi: MasterWebUI = null
  // master url
  private val masterUrl = address.toSparkURL
  // master weburl
  private var masterWebUiUrl: String = _
  // master节点状态
  private var state = RecoveryState.STANDBY
  // 如果没有指定,则默认最大核心数为Int最大值
  private val defaultCores = conf.getInt("spark.deploy.defaultCores", Int.MaxValue)

3.2 Master的onStart()方法 

    下面我们来看下Master的onstart方法干了哪些事:

    我们看一下 self.send(CheckForWorkerTimeOut) :

    这个self是RpcEndpointRef,这里也就是Master的引用,我把实现贴在下面:

    NettyRpcEnv.scala

 

     Dispatcher发送出一条OneWayMessage(不需要回复的)。我们接着往下看:

看一下data.inbox.post(message):

     这时,消息已经存放在Master的inbox中,当Dispatcher的轮询线程执行到时,会调用inbox.process处理这条消息,inbox.process()方法这里不再细说(2.1.2),我们直接看对应片段(由dispatcher.postOneWayMessage(message)知道是一条OneWayMessage):

    此处的endpoint.receive即是Master的receive方法,我们看一下:

    Master的receive方法根据接收到的数据类型进行模式匹配,我们看下CheckForWorkerTimeOut数据类型干了什么:

    我们看下timeOutDeadWorkers()

 至于worker删除的细节,这里就不看了。我们回到Master的onStart方法。

 

    至此,Master的启动已经完成。我们简单总结一下:

    首先,初始化了Master rpcEnv环境,初始化了Rpc通信的相关组件,并在Dispatcher和Inbox中添加了启动数据。初始化一个Master对象,定义了一大堆变量:hadoop配置,worker超时时间、任务恢复模式、worker列表、app列表,驱动、webui等等。之后调用Master的onStart方法,正式启动Master。

      Master的onStart方法给自己发送了一个CheckForWorkerTimeOut,用于检查是否有超时的worker,如果有则移除。

    这一篇到这里吧,以后有新的理解再更新。下一篇我们学习一下Worker的启动过程。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章