SparkContext 初始化过程源码说明

本文详细剖析了Spark任务提交流程,从SparkContext初始化到任务执行的全过程,包括关键组件的创建与交互,以及任务如何最终到达Executor执行。

前言

本篇主要的目的是阐述 SparkContext 初始化过程中,重要环节源码的逻辑流程的梳理。SparkContext 实例化的过程是一个比较复杂的过程,主要包括SparkEnv、spark-history、心跳检测、状态追踪、广播、资源与任务调度、底层通信等等组件的初始化。本篇文章的主要目的在于:了解 Spark 提交任务底层是怎样将 Task 任务提交至 Executor 中;了解 SparkContext 初始化过程中几个重要的环节。

Spark 任务提交大致流程

流程说明

spark任务运行流程图解

  1. 经过 SparkSubmit 的提交之后就会准备运行环境(包括:资源、SparkContext初始化等等),然后开始提交 Spark Job 任务运行;
  2. 当遇到动作算子(如:reduce、collect等等)的时候就会开始提交 Job,这一类算的底层一定会执行runJob()方法并提交到 DAGschedule中;
  3. 而后通过 DAGSchedulerEventProcessLoop(循环事务处理器)处理提交 Job,然后开始递归分段提交任务至 TaskSchedule(实际为继承的子类 TaskSchedulerImpl);
  4. 实际上到了这一步 Task 任务已经切分好了,并且准备提交给 Executor 执行;但是怎么直接将 Task 提交给Executor运行;,这里就需要 ScheduleBackend (后端调度器)将 Task 分发给各个 Executor;
  5. ScheduleBackend (实际为继承的子类 CoarseGrainedSchedulerBackend)开始通过 launchTasks 提交 Task任务至 Executor 中;
  6. ExecutorBackend (实际为继承的子类 CoarseGrainedExecutorBackend)接收到 Task 任务时,就会提交给 Executor 开始运行;
  7. Executor 接收到 Task任务时候就会开始执行;

涉及源码说明

执行Job
org.apache.spark.rdd.RDD

// 这里是以 reduce 算子为例进行说明
def reduce(f: (T, T) => T): T = withScope {
   
   
    val cleanF = sc.clean(f)
		................. 中间省略部分代码 ....................
      
//    通过SparkContext 开始提交Job
    sc.runJob(this, reducePartition, mergeResult)
    // Get the final result out of our Option, or throw an exception if the RDD was empty
    jobResult.getOrElse(throw new UnsupportedOperationException("empty collection"))
  }
org.apache.spark.SparkContext
  
def runJob[T, U: ClassTag](
      rdd: RDD[T],
      processPartition: Iterator[T] => U,
      resultHandler: (Int, U) => Unit)
  {
   
   
    val processFunc = (context: TaskContext, iter: Iterator[T]) => processPartition(iter)
      runJob[T, U](rdd, processFunc, 0 until rdd.partitions.length, resultHandler)
  }
org.apache.spark.SparkContext
  
def runJob[T, U: ClassTag](
      rdd: RDD[T],
      func: (TaskContext, Iterator[T]) => U,
      partitions: Seq[Int],
      resultHandler: (Int, U) => Unit): Unit = {
   
   
    ................. 中间省略部分代码 ....................
      
//    将任务提交至 DAGscheduler 进行Job 任务的划分
    dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, resultHandler, localProperties.get)
    progressBar.foreach(_.finishAll())
    rdd.doCheckpoint()
  }
提交 Stage
org.apache.spark.scheduler.DAGScheduler
  
def runJob[T, U](
      rdd: RDD[T],
      func: (TaskContext, Iterator[T]) => U,
      partitions: Seq[Int],
      callSite: CallSite,
      resultHandler: (Int, U) => Unit,
      properties: Properties): Unit = {
   
   
    val start = System.nanoTime
//    提交 Job
    val waiter = submitJob(rdd, func, partitions, callSite, resultHandler, properties)
		
    ................. 中间省略部分代码 ....................
    }
  }
org.apache.spark.scheduler.DAGScheduler
  
def submitJob[T, U](
      rdd: RDD[T],
      func: (TaskContext, Iterator[T]) => U,
      partitions: Seq[Int],
      callSite: CallSite,
      resultHandler: (Int, U) => Unit,
      properties: Properties): JobWaiter[U] = {
   
   
    ................. 中间省略部分代码 ....................
      
    assert(partitions.size > 0)
    val func2 = func.asInstanceOf[(TaskContext, Iterator[_]) => _]
    val waiter = new JobWaiter(this, jobId, partitions.size, resultHandler)
//    通过循环事务处理提交 Job
    eventProcessLoop.post(JobSubmitted(
      jobId, rdd, func2, partitions.toArray, callSite, waiter,
      SerializationUtils.clone(properties)))
    waiter
  }
org.apache.spark.scheduler.DAGSchedulerEventProcessLoop
/**
   * @Author: Small_Ran
   * @Date: 2022/6/1
   * @Description: 根据 driver 发送过来的 事件类型,来决定到底做什么
   */
private def doOnReceive(event: DAGSchedulerEvent): Unit = event match {
   
   
//      Job提交事务类型  
  case JobSubmitted(jobId, rdd, func, partitions, callSite, listener, properties) =>
      dagScheduler.handleJobSubmitted(jobId, rdd, func, partitions, call
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值