2018-05-18

最近准备把自己看大神源码的一些心得总结写下来,平时看了总是会忘记,记下来,随时翻出来看看。

第一篇讲Spark中最重要的SparkContext,他是Spark的核心,虽说在Spark2中已经用SparkSession来作为我们初始化的对象,但是最最核心核心的还是SparkContext。

SparkContext有一个参数SparkConf 是一个存储运行参数的地方,这个参数是不能在运行中修改的,对外调用的方法中都是SparkConf的clone,SparkConf有三个重要的参数,spark.master,spark.submit.deployMode,spark.app.name。

源码如下所示:

def master: String = _conf.get("spark.master")

  def deployMode: String = _conf.getOption("spark.submit.deployMode").getOrElse("client")

  def appName: String = _conf.get("spark.app.name")

master代表有local,standalone,yarn,mesos

deployment有client和cluster。

SparkContext有以下几个重要组件

1,_env: SparkEnv

2,_schedulerBackend: SchedulerBackend

3,_taskScheduler: TaskScheduler

4,_dagScheduler: DAGScheduler

5,_executorAllocationManager: Option[ExecutorAllocationManager]

6,_listenerBus: LiveListenerBus

7,_statusTracker: SparkStatusTracker

这里看一下_schedulerBackend,_taskScheduler和_dagScheduler的初始化

val (sched, ts) = SparkContext.createTaskScheduler(this, master, deployMode)

这里返回的是一个元组tuple赋值给我们的两个变量,

_schedulerBackend = sched

    _taskScheduler = ts

以及生成  _dagScheduler

    _dagScheduler = new DAGScheduler(this)

createTaskScheduler方法是依据设置的master和deployment来获取对应的实现类

这里主要讲一下Spark On  Yarn的获取方式

case masterUrl =>

        val cm = getClusterManager(masterUrl) match {

          case Some(clusterMgr) => clusterMgr

          case None => throw new SparkException("Could not parse Master URL: '" + master + "'")

        }

        try {

          val scheduler = cm.createTaskScheduler(sc, masterUrl)

          val backend = cm.createSchedulerBackend(sc, masterUrl, scheduler)

          cm.initialize(scheduler, backend)

          (backend, scheduler)

        } catch {

          case se: SparkException => throw se

          case NonFatal(e) =>

            throw new SparkException("External scheduler cannot be instantiated", e)

        }

getClusterManager方法根据master参数返回对应的Clustermanager,通过ServiceLoader加载了所有的ExternalClusterManager实现类通过其canCreate方法过滤出我们想要的。这里的得到的是YarnClusterManager 这个类的 canCreate如下

override def canCreate(masterURL: String): Boolean = {

    masterURL == "yarn"

  }

TaskScheduler的生成方法:

override def createTaskScheduler(sc: SparkContext, masterURL: String): TaskScheduler = {

    sc.deployMode match {

      case "cluster" => new YarnClusterScheduler(sc)

      case "client" => new YarnScheduler(sc)

      case _ => throw new SparkException(s"Unknown deploy mode '${sc.deployMode}' for Yarn")

    }

  }

可见如果是Spark on Yarn的cluster模式返回YarnClusterScheduler如果是client模式返回YarnScheduler,YarnClusterScheduler是YarnScheduler的子类,YarnClusterScheduler重写了postStartHook方法,

override def postStartHook() {

//这里是给Yarn-Cluster模式下ApplicationMaster的sc赋值说明sc已经初始化完毕

    ApplicationMaster.sparkContextInitialized(sc)

    super.postStartHook()//调用父类的postStartHook方法

    logInfo("YarnClusterScheduler.postStartHook done")

  }

YarnScheduler是TaskSchedulerImpl的子类,重写了父类的getRackForHost

// By default, rack is unknown

  override def getRackForHost(hostPort: String): Option[String] = {

    val host = Utils.parseHostPort(hostPort)._1

    Option(RackResolver.resolve(sc.hadoopConfiguration, host).getNetworkLocation)

  }

父类TaskSchedulerImpl是管理Task的类

因为Yarn支持机架感知所有只有SparkOnYarn 才有这个功能

SchedulerBackend的生成方法

override def createSchedulerBackend(sc: SparkContext,

      masterURL: String,

      scheduler: TaskScheduler): SchedulerBackend = {

    sc.deployMode match {

      case "cluster" =>

        new YarnClusterSchedulerBackend(scheduler.asInstanceOf[TaskSchedulerImpl], sc)

      case "client" =>

        new YarnClientSchedulerBackend(scheduler.asInstanceOf[TaskSchedulerImpl], sc)

      case  _ =>

        throw new SparkException(s"Unknown deploy mode '${sc.deployMode}' for Yarn")

    }

  }

很明显Yarn-Cluster返回YarnClusterSchedulerBackend,Yarn-Client返回YarnClientSchedulerBackend 然后SchedulerBackend会作为TaskScheduler初始化initialize参数,后面再写。

_dagScheduler直接用 new DAGScheduler(this)方式赋值,这个是生成DAG有向无环图的类

你可能感兴趣的:(2018-05-18)