spark2.11-2.3源码1_SparkContext初始化

SparkContext初始化

HeartbeatReceiver:
我们需要在“createTaskScheduler”之前注册“heartbeatReceiver”,因为执行器将在构造函数中检索“heartbeatReceiver”。

HeartbeatReceiver所在文件为HeartbeatReceiver.scala,该文件开始部分包含一些HeartbeatReceiver接受/返回的消息类的定义: Heartbeat表示executors发给driver的心跳信息; TaskSchedulerIsSet是SparkContext通知HeartbeatReceiver;
taskScheduler已经创建好; ExpireDeadHosts用于通知HeartbeatReceiver将已经没有心跳的Host销毁掉; ExecutorRegistered, ExecutorRemoved表示Executor的注册和移除; HeartbeatResponse是HeartbeatReceiver处理Heartbeat消息后返回的消息。

 _heartbeatReceiver = env.rpcEnv.setupEndpoint(
      HeartbeatReceiver.ENDPOINT_NAME, new HeartbeatReceiver(this))
 _heartbeatReceiver.ask[Boolean](TaskSchedulerIsSet)

SparkContext.createTaskScheduler

**第一步创建TaskSchedulerImpl,第二步创建需要的SchedulerBackend,第三步scheduler初始化scheduler.initialize**
相关内容如下:
 val (sched, ts) = SparkContext.createTaskScheduler(this, master, deployMode)
    _schedulerBackend = sched
    _taskScheduler = ts

> SparkContext.createTaskScheduler方法内部:首先根据不同的提交模式,例如本地等,创建不同的taskScheduler
> 不同的提交模式为以下四种,相比spark1少了MESOS_REGEX(Mesos集群资源管理器运行模式)和SIMR_REGEX(匹配Spark in MapReduce v1,用于兼容老版本的Hadoop集群)两种模式,暂时还不清楚为什么。

SparkMasterRegex {
 // 正则表达式,用于匹配local[N] 和 local[*]
  val LOCAL_N_REGEX = """local\[([0-9]+|\*)\]""".r
  // 正则表达式,用于匹配local[N, maxRetries], maxRetries表示失败后的最大重复次数
  val LOCAL_N_FAILURES_REGEX = """local\[([0-9]+|\*)\s*,\s*([0-9]+)\]""".r
  //正则表达式,用于匹配local-cluster[N, cores, memory],它是一种伪分布式模式
  val LOCAL_CLUSTER_REGEX = """local-cluster\[\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*]""".r
  // 正则表达式用于匹配 Spark Standalone集群运行模式
  val SPARK_REGEX = """spark://(.*)""".r

TaskSchedulerImpl:
1底层通过操纵一个SchedulerBackend,针对不同种类cluster(standalone、yarn)调度task
2也可以通过使用一个LocalBackend,并且将isLocal参数设置为true,在本地模式下工作
3负责处理一些通用的逻辑,比如说决定多个job的调度顺序,启动推测任务执行
4客户端首先应用调用它的initialize()方法和start()方法,然后通过runTasks()方法提交task sets

SchedulerBackend(接口),多种实现类:
维护executor相关信息(包括executor的地址、通信端口、host、总核数,剩余核数),手头上executor有多少被注册使用了,有多少剩余,总共还有多少核是空的等等

scheduler.initialize(backend)中schedulableBuilder.buildPools()匹配什么策略(FIFO/FAIR)创建什么调试池

TaskScheduler.start()

**注:**对于Standalone模式,由以前的SparkDeploySchedulerBackend改成了现在的StandaloneSchedulerBackend

1:首先构造ApplicationDescription(代表当前执行的application的一些情况,包括application最大需要多少cpu core,每个slave上需要多少内存,非常重要!)
 val appDesc = ApplicationDescription(sc.appName, maxCores, sc.executorMemory, command,
      webUrl, sc.eventLogDir, sc.eventLogCodec, coresPerExecutor, initialExecutorLimit)
2:创建AppClient,现在改叫StandaloneAppClient(***允许应用程序与Spark独立群集管理器通信的接口***。获取集群事件的主URL、应用程序描述和侦听器,并在发生各种事件时调用侦听器。)
client = new StandaloneAppClient(sc.env.rpcEnv, masters, appDesc, this, conf)
client.start()
3:
client.start()中启动ClientEndpoint线程,调用registerWithMaster,里面调用tryRegisterAllMasters连接所有的Master,把applicating信息发给Master,Master进行注册
override def onStart(): Unit = {
      try {
        registerWithMaster(1)
        }
 }
private def registerWithMaster(nthRetry: Int) {
      registerMasterFutures.set(tryRegisterAllMasters())
 }
 private def tryRegisterAllMasters(): Array[JFuture[_]] = {
	 val masterRef = rpcEnv.setupEndpointRef(masterAddress, Master.ENDPOINT_NAME)
	 masterRef.send(RegisterApplication(appDescription, self))
 }

SparkContext创建DAGScheduler: _dagScheduler = new DAGScheduler(this)

DAGScheduler:实现了面向stage的调度机制的高层次的调度层。它会为每个job计算一个stage的DAG(有向无环图),追踪RDD和stage的输出是否被物化了(物化就是写入了磁盘或者内存等地方),并且寻找一个最少消耗调度机制来运行job。
它会将 stage作为tasksets提交到底层的TaskSchedulerImpl上,来在集群上运行它们(task)
除了处理stage的DAG,它还负责决定运行每个task的最佳位置,基于当前的缓存状态,将这些最佳位置提交给底层TaskSchedulerImpl。此外,它会处理由于shuffle输出文件丢失导致的失败。在这种情况下,旧的stage可能就会被重新提交。一个stage内部的失败,如果不是由于shuffle文件丢失所导致的,会被TaskScheduler处理,它会多次重试每一个task,直到最后,实在不行了,才会去取消整个stage.

SparkContext创建SparkUI(相当于Spark应用程序):SparkUI.create(Some(this), _statusStore, _conf, _env.securityManager, appName, "", startTime)

会启动一个Jetty,端口4040,new一个SparkUI对象
new SparkUI(store, sc, conf, securityManager, appName, basePath, startTime, appSparkVersion)

猜你喜欢

转载自blog.csdn.net/u011607686/article/details/86503905
今日推荐