Spark实战(3)_SparkContext原理剖析与源码分析

TaskScheduler的初始化机制

TaskScheduler,如何注册Application,executor如何反向注册?

TaskScheduler的初始化机制TaskScheduler的初始化机制

  1. createTaskScheduler(),内部会创建三个东西。
  2. 一是TaskSchedulerImpl,它其实就是我们所说的TaskScheduler。
  3. 二是SparkDeploySchedulerBackend,它在底层会负责接收TaskSchedulerImpl的控制,实际上负责与Master的注册,Ececutor的反注册,task发送到executor等操作。
  4. 调用TaskSchedulerImpl的init()方法,创建SchedulerPool,当DAGScheduler要让TaskScheduler去调度一些任务的时候,就会把这些任务放到调度池里面,它有不同的优先策略,比如FIFO。
  5. 调用TaskSchedulerImpl的start()方法,方法内部调用SparkDeploySchedulerBackend的start()方法。
  6. SparkDeploySchedulerBackend的start()方法,创建一个东西,AppClient。
  7. AppClient,启动一个线程,创建一个ClientActor。
  8. ClientActor线程,调用两个方法,registerWithMaster()——>tryRegisterAllMasters()。
  9. registerWithMaster()——>tryRegisterAllMasters(),向MasterActor发送RegisterApplication(case class,里面封装了Application的信息)。
  10. RegisterApplication发送数据到Spark集群的Master——>Worker——>Executor。
  11. Executor反向注册到SparkDeploySchedulerBackend上面去。

TaskSchedulerImpl底层实际主要基于SparkDeploySchedulerBackend来工作。

DAGScheduler

DAGSchedulerEventProcessActor,DAGScheduler底层基于该组件进行通信。(线程)

SprkUI

SprkUI,显示Application运行的状态,启动一个jetty服务器,来提供web服务,从而显示网页。

源码分析

package org.apache.spark,SparkContext.scala

 1// Create and start the scheduler
 2  private[spark] var (schedulerBackend, taskScheduler) =
 3    SparkContext.createTaskScheduler(this, master)
 4// 这是我们常用的Sparkt提交模式中的standalone方式
 5      case SPARK_REGEX(sparkUrl) =>
 6        val scheduler = new TaskSchedulerImpl(sc)
 7        val masterUrls = sparkUrl.split(",").map("spark://" + _)
 8        val backend = new SparkDeploySchedulerBackend(scheduler, sc, masterUrls)
 9        scheduler.initialize(backend)
10        (backend, scheduler)

package org.apache.spark.scheduler,TaskSchedulerImpl.scala

 1/**
 2  * 1、底层通过操作一个SchedulerBackend,针对不同种类的cluster(standlalone、yarn、mesos),调度task
 3  * 2、它也可以通过使用一个LacalBackend,并且将isLocal参数设置为true,来在本地模式下工作
 4  * 3、它负责处理一些通用的逻辑,比如说决定多个job的调度顺序,启动推测任务执行
 5  * 4、客户端首先应该调用它的initialize()方法和start()方法,然后通过runTasks()方法提交task sets
 6  */
 7def initialize(backend: SchedulerBackend) {
 8    this.backend = backend
 9    // temporarily set rootPool name to empty
10    rootPool = new Pool("", schedulingMode, 0, 0)
11    schedulableBuilder = {
12      schedulingMode match {
13        case SchedulingMode.FIFO =>
14          new FIFOSchedulableBuilder(rootPool)
15        case SchedulingMode.FAIR =>
16          new FairSchedulableBuilder(rootPool, conf)
17      }
18    }
19    schedulableBuilder.buildPools()
20  }

start()方法,

 1// start()方法,sparkContext.scala
 2// start TaskScheduler after taskScheduler sets DAGScheduler reference in DAGScheduler's
 3  // constructor
 4  taskScheduler.start()
 5// TaskSchedulerImpl.scala
 6override def start() {
 7    backend.start()
 8// SparkDeploySchedulerBackend.scala    
 9override def start() {
10    super.start()
11// 这个ApplicationDescription,非常重要
12    // 它就代表了当前执行的这个application的一些情况
13    // 包括application最大需要多少cpu core,每个slave上需要多少内存
14    val appDesc = new ApplicationDescription(sc.appName, maxCores, sc.executorMemory, command,
15      appUIAddress, sc.eventLogDir, sc.eventLogCodec)
16    // 创建了AppClient
17    client = new AppClient(sc.env.actorSystem, masters, appDesc, this, conf)
18    client.start()

package org.apache.spark.deploy.client,AppClient.scala,

 1/**
 2  * 这是一个接口
 3  * 它负责为application与Spark集群进行通信
 4  * 它会接收一个spark master的url,以及一个ApplicationDescripition,和一个集群事件的监听器,以及各种事件发生时,
 5  * 监听器的回调函数
 6  */
 7def start() {
 8    // Just launch an actor; it will call back into the listener.
 9    actor = actorSystem.actorOf(Props(new ClientActor))
10  }

package org.apache.spark.scheduler,DAGScheduler

 1@volatile private[spark] var dagScheduler: DAGScheduler = _
 2  try {
 3    dagScheduler = new DAGScheduler(this)
 4  } catch {
 5    case e: Exception => {
 6      try {
 7        stop()
 8      } finally {
 9        throw new SparkException("Error while constructing DAGScheduler", e)
10      }
11    }
12  }
13/**
14  * 实现了面向stage的调度机制的高层次的调度层。它会为每个job计算一个stage的DAG(有向无环图),
15  * 追踪RDD和stage的输出是否被物化了(物化就是写入了磁盘或内存等地方),并且寻找一个最少消耗(最优、最小)调度机制来运行job。
16  * 它会将stage作为tasksets提交到底层的TaskSchedulerImpl上,来在集群上运行它们(task)。
17  *
18  * 除了stage的DAG,它还负责决定运行每个task的最佳位置,基于当前的缓存状态,将这些最佳位置提交给底层的TaskSchedulerImpl。
19  * 此外,它还会处理由于shuffle输出文件丢失导致的失败,在这种情况下,旧的stage可能会被重新提交。
20  * 一个stage内部的失败,如果不是由于shuffle文件丢失所导致的,会被TaskScheduler处,它会多次重试每一个task,直到最后,实在不行了,
21  * 才会去取消整个stage。
22  */

the Spark UI,

1// Initialize the Spark UI
2  private[spark] val ui: Option[SparkUI] =
3    if (conf.getBoolean("spark.ui.enabled", true)) {
4      Some(SparkUI.createLiveUI(this, conf, listenerBus, jobProgressListener,
5        env.securityManager,appName))
6    } else {
7      // For tests, do not enable the UI
8      None
9    }

本文首发于steem,感谢阅读,转载请注明。

https://steemit.com/@padluo


微信公众号「padluo」,分享数据科学家的自我修养,既然遇见,不如一起成长。

数据分析数据分析


读者交流电报群

https://t.me/sspadluo


知识星球交流群

知识星球读者交流群知识星球读者交流群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值