Spark (源码) 总结-杂

-1- .Driver 启动的过程

1.spark-submit 脚本,在脚本里调用了org.apache.spark.deloy.SparkSubmit 类

2.SparkSubmit.scala  main方法

 override def main(args: Array[String]): Unit = {
    val appArgs = new SparkSubmitArguments(args)
    if (appArgs.verbose) {
      // scalastyle:off println
      printStream.println(appArgs)
      // scalastyle:on println
    }
    appArgs.action match {
      case SparkSubmitAction.SUBMIT => submit(appArgs)
      case SparkSubmitAction.KILL => kill(appArgs)
      case SparkSubmitAction.REQUEST_STATUS => requestStatus(appArgs)
    }
  }

3.SparkSubmit.scala  submit(appArgs)方法

 private def submit(args: SparkSubmitArguments): Unit = {
    val (childArgs, childClasspath, sysProps, childMainClass) = prepareSubmitEnvironment(args)

    
    if (args.isStandaloneCluster && args.useRest) {
      try {
        // scalastyle:off println
        printStream.println("Running Spark using the REST application submission protocol.")
        // scalastyle:on println
        doRunMain()
      } catch {
        // Fail over to use the legacy submission gateway
        case e: SubmitRestConnectionException =>
          printWarning(s"Master endpoint ${args.master} was not a REST server. " +
            "Falling back to legacy submission gateway instead.")
          args.useRest = false
          submit(args)
      }
    // In all other modes, just run the main class as prepared
    } else {
      doRunMain()
    }
  }

4.SparkSubmit.scala  runMain()

   该方法主要是 确定mainClass,使用classFromName,获取类对象,然后采用映射调用main方法

   本次假设mainClass 为Client.scala,解释:Application提交过程

5.Client  main方法

在main方法中,new ClientEndPoint 对象创建过程中,会向Master发送RegisterDriver消息。

object Client {
  def main(args: Array[String]) {
    // scalastyle:off println
    if (!sys.props.contains("SPARK_SUBMIT")) {
      println("WARNING: This client is deprecated and will be removed in a future version of Spark")
      println("Use ./bin/spark-submit with \"--master spark://host:port\"")
    }
    // scalastyle:on println

    val conf = new SparkConf()
    val driverArgs = new ClientArguments(args)

    if (!conf.contains("spark.rpc.askTimeout")) {
      conf.set("spark.rpc.askTimeout", "10s")
    }
    Logger.getRootLogger.setLevel(driverArgs.logLevel)

    val rpcEnv =
      RpcEnv.create("driverClient", Utils.localHostName(), 0, conf, new SecurityManager(conf))

    val masterEndpoints = driverArgs.masters.map(RpcAddress.fromSparkURL).
      map(rpcEnv.setupEndpointRef(_, Master.ENDPOINT_NAME))
    rpcEnv.setupEndpoint("client", new ClientEndpoint(rpcEnv, driverArgs, masterEndpoints, conf))

    rpcEnv.awaitTermination()
  }
}

6. 之后就是Driver 启动,SparkContext初始化的过程了

-2- .Executor启动相关

1.Master shchedula()方法中,worker.endPoint.send(LaunchExecutor)请求的时候,同步发送了一份信息给app.driver: exec.application.driver.send(ExecutorAdded) ,所以在ExecutorBackEnd启动向Driver注册之前,Driver就已经知道了该executor的存在,只不过状态还未更改。

2.Worker 在启动Executor的时候,先new ExecutorRunner,runner不是进程也不是线程,只是一个对象,在runner.start()中,使用线程异步 启动了一个线程,该线程用于启动executorBackEnd.

3.executor运行结束之后,使用backend.updateStatus() 向schedulerBackEnd 发送消息,schedulerBackEnd 的receive中,会把结果交给taskSchedular进行处理,然后按照处理的结果在进行相关操作,比如,如果运行成功不需要重试,那么schedulerBackEnd,就会把cores加到freeCores中,然后调用makeOffers() 重新进行task的资源分配,看有没有满足资源条件的task可以运行。

-3- .任务调度相关

job提交之后,调用runjob,到最终task被分配到executor之前所涉及到的调度相关

1.首先涉及到的调度是job  stage 划分和提交过程,也就是submitStage方法,所有又依赖的Satge,也就是说有父Satge的子Stage,子Stage调用submitSatge的时候,会将子Satge添加到watingSatge队列中,换句话说,如果一个Stage有父依赖,那么他就不能被subnitMissingSatge  submit,会被加入到watingSatge,只有没有依赖的Satge才会被提交。

    没有依赖的Stage提交,会将Satge转换成tasksetManager,提交给TaskScheduar

2.taskSchedular在初始化的时候,方法位于sparkcontext中,初始化的时候初始化了一个队列,这个队列有两个选择:FIFO/FAIR,

tasksetManager提交给taskSchedular的时候就会加入到该队列中,比如FIFO队列,有两层排序,一层是根据jobid,jobid越小的优先级越高,同一job内部,存在第二层排序,stageid,stageid越小的优先级越高

值得足以的一点就是:stage提交的时候,有依赖,就不会添加到队列中,会加入到watingSatge中,等待某一个stage完成之后,会检查watingSatge提交已经没有依赖的Stage

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值