Spark-Scheduler:三、DAGScheduler实现过程

前言:

通过前面部分内容,我们知道DAGScheduler会根基RDD的计算逻辑,将DAG划分为不同的Stage,每个Stage可以并发执行一组逻辑完全相同的Task,只是分布作用于不同数据集上面。

 

现在从一个简单的RDD count为例,来看一下Spark的内部实现原理。

 

1、SparkContext#runJob

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

其实SparkContext实现了很多runJob,这些函数的区别就是调用参数不同,但是这些runJob最后都会

调用DAGSchedulerrunJob:

dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, allowLocal, resut)

DAGSchedulerrunJob会开始对用户提交的Job进行处理,包括Stage的划分、Task的生成等。

TaskScheduler是通过SparkContext#createTaskScheduler创建,而DAGScheduler时直接调用它的构造函数创建。只不过DAGScheduler保存了TaskScheduler的引用,因此需要在TaskScheduler创建之后进行创建。

sparkContext中创建DAGScheduler

dagScheduler = new DAGScheduler(this);

这个构造函数的实现是:

def this(sc: SparkContext) = this(sc, sc.taskScheduler)

继续看this(sc, sctaskScheduler)的实现:

def this(sc: SparkContext, taskScheduler:TaskScheduler) = {
this(
sc,
taskScheduler,
sc.listenerBus,
sc.env.mapOutTracker.asInstanceOf[MapOutputTrackerMaster],
sc.env.blockManager.master
sc.env
)
}

this(sc, sc,taskScheduler)通过调用下面的构造函数完成DAGScheduler的创建:

private[spark]

class DAGScheduler(

private[scheduler] val sc : SparkContext,

private[scheduler] val taskScheduler: TaskScheduler,

listenerBus: LiverListenerBus,

mapOutputTracker: MapOutputTrackerMaster, //shuffle map task 的输出,下游的task可以获取shuffle的位置信息

blockManagerMaster: BlockManagerMaster, //在Driver端管理整个Job的Block的信息。

env: SparkEnv,

clock: Clock = SystemClock

)extends Logging{}

这里我们看见DAGScheduler初始化的都是集群状态信息的数据结构,对于监管它还会创建一个Actor(org.apache.spark.scheduler.DAGSchedulerEventProcessActor),变量名为event-ProcessActor

。这个Actor的主要职责就是处理DAGScheduler发送给它的各种消息;

def receive = {

case p: Props => sender ! context.actorOf(p)

case _=> logWarning("received unknown message in DAGSchedulerActorSupervis")

}

//DAGSchedulerEventProcessActor的创建过程

implicit val timeout = Timeout(30 seconds)

val initEventActorReply = dagSchedulerActorSupervisor ? Props(new DAGSchedulerEventProcessActor(this))

eventProcesActor = Await.result(initEventActorReply, timeout.duration).asInstanceOf[ActorRef]

DAGSchedulerActorSupervisor来完成eventProcessActor的创建。如果Actor出现错误,则取消DAGScheduler的所有job,停止SparkContext,最终退出。

2、count具体的执行过程

言归正传前面是介绍了DAGScheduler的内部创建机制,以及我们在调用count的时候sparkContext是如何调用,已经如何创建DAGSchedulerTaskScheduler的。

那么抛开方法里面的细节,整个count的执行流程如下

 

由上面图可大致了解count执行的具体过程,第三到第四步的实现:

val waiter = submitJob(rdd, func, partitions, callSite, allowLocal, resultHandler)

waiter.awaitResult() match{

case JobSucceeded => {

logInfo("Job %d finished: %s, took %f s".format(waiter.jobId,callSite.shotForm,(System.nanoTime - strat)/1e9))

case JobFailed(exception: Exception) =>

logInfo("Job %d failed: %s, took %f s").format(waiter.jobId, callSite.shortForm, (System.nanoTIme - start)/1e9)

}

}

上述submitJob首先会为这个Job生成一个Job ID,并且生成一个JobWaiter的实里来监听Job的执行情况:

val waiter = new JobWaiter(this, jobId, partitions.size, resultHandler)

JobWaiter会监听Job的执行状态,而Job是由多个Task组成的,因此只有Job的所有Task都成功完成,Job才标记成功。当其中一个Task失败,都会标记Job失败,这是DAGScheduler通过调用org.apache.spark.scheduler.JobWaiter#jobFailed实现的。

最后,DAGScheduler会向eventProcessActor提交该Job:

eventProcessActor ! JobSubmitted()

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值