Spark DAGScheduler源码分析系列之三: Job提交&Stage划分&提交

概述

前面我们分析了DAG中相关的基础变量以及事件处理器,我们知道RDD是Spark操作的基本数据结构,RDD提供了两种类型的操作:transformationactiontransformation采用的懒策略,如果只是将transformation提交是不会执行计算的,计算只有在action被提交的时候才被触发,只有在action的方法中才会调用org.apache.spark.SparkContext#runJob方法来提交Job,本节我们来分析下Job提交以及Stage的生成&提交过程

触发Job生成

我们先来看下Job是如何触发以及提交的,首先我们知道action算子才会执行真正的计算,是划分job的标识,所以当我们触发action算子时候,就会触发job,然后进行提交,我们来看下count这个action算子是如何得到Job以及提交Job的。我们来看下count算子,主要是通过sparkContext的runJob来进行Job创建,提供了count计算需要的funciton:

def count(): Long = sc.runJob(this, Utils.getIteratorSize _).sum

我们跟踪下SparkContext里面runJob实现,会经过几个runJob的转换,添加partition,结果处理函数,进行一些清理工作之后,最终在该方法中将提交请求转发到了dagScheduler

def runJob[T, U: ClassTag](rdd: RDD[T], func: Iterator[T] => U): Array[U] = {
   
  runJob(rdd, func, 0 until rdd.partitions.length)
}

def runJob[T, U: ClassTag](rdd: RDD[T], func: Iterator[T] => U,
  partitions: Seq[Int]): Array[U] = {
   
  val cleanedFunc = clean(func)
  runJob(rdd, (ctx: TaskContext, it: Iterator[T]) => cleanedFunc(it), partitions)
}

// resultHandler是将结果填充result数组,返回数组结果信息
def runJob[T, U: ClassTag](rdd: RDD[T], func: (TaskContext, Iterator[T]) => U,
  partitions: Seq[Int]): Array[U] = {
   
  val results = new Array[U](partitions.size)
  runJob[T, U](rdd, func, partitions, (index, res) => results(index) = res)
  results
}

def runJob[T, U: ClassTag](rdd: RDD[T], func: (TaskContext, Iterator[T]) => U,
  partitions: Seq[Int],  resultHandler: (Int, U) => Unit): Unit = {
   
  val callSite = getCallSite
  // 对传入给算子的操作进行清理检查
  val cleanedFunc = clean(func)
  // 将DAG及RDD提交给DAGScheduler进行调度
  dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, resultHandler, localProperties.get)
  progressBar.foreach(_.finishAll())
  rdd.doCheckpoint() // 保存检查点
}

DagScheduler里面的runJob是真正在给定RDD上运行一个Job,结果交给resultHandler处理,主要是将各个结果的数据填充结果Array,返回给Driver,该函数会通过submitJob来提交job,并进行等待结果处理完成。

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,该方法是异步的,会立即返回JobWaiter对象
  val waiter = submitJob(rdd, func, partitions, callSite, resultHandler, properties)
  // 提交Job,该方法是异步的,会立即返回JobWaiter对象
  val awaitPermission = null.asInstanceOf[scala.concurrent.CanAwait]
  // 等待Job处理完毕
  waiter.completionFuture.ready(Duration.Inf)(awaitPermission)
  // 获取运行结果
  waiter.completionFuture.value.get match {
   
    case scala.util.Success(_) => // Job执行成功
    logInfo("Job %d finished: %s, took %f s".format
            (waiter
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值