spark任务调度源码浅析

废话:
因为前几天比较了idea和eclipse感觉查询上idea好用,想试试idea,但是用它挖了几天源码后。idea不熟练,挖代码苦不堪言,再度回到eclipse中。

**前言:**上篇已经讲解过spark1.6版本中资源调度的源码,standalone-cluster模式如何实现。今天再扒一扒spark中任务调度的实现。大家都知道,大数据中,计算向数据移动,我个人理解的其实就是计算向资源移动,那么spark中是如何将你提交的app计算任务,分配到集群中各个计算节点中的呢?

逻辑实现分析:我们以client模式讲解下(cluster类同,只不过是将启动driver的方式交给了master,master再去找一台资源充足的启动driver,上篇说过),client提交一个app的任务给driver,当代码中执行action算子之后,driver中会根据DAGScheduler执行action算子,根绝app划分宽窄依赖,然后形成DAG,生成很多stage,每一个stage包含一组task;taskschduler遍历task集合集合,发送task任务到worker节点上的的exeutor上执行。

在这里插入图片描述

一、寻找程序入口
1。我们以图中伪代码为例,寻找action算子,找到触发driver的入口。我们找到RDD这个类中foreach算子的位置。
在这里插入图片描述
2。 点击跟踪sc.runJob,追踪n多runJob
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
3.找到这里,我们可以看到,仍然在SparkcContext这个类中,dagScheduler开始划分宽窄依赖
在这里插入图片描述
4。点击dagScheduler.runJob,找到核心方法submitJob

在这里插入图片描述

在这里插入图片描述
二、Job分析(这里比较绕)
1.这里用eventProcessLoop.post方法,传了一个JObsubmit的方法。

在这里插入图片描述
2。点进post方法,可以看到,把submit的方法放到了队列里面。
在这里插入图片描述

这个queue是一个BlockingQueue

在这里插入图片描述
3.但是在哪里真正启动这个线程呢?我们返回上面的eventProcessLoop.post 方法,点击eventProcessLoop,找到他的定义。
在这里插入图片描述

4。点击DAGSchedulerEventProcessLoop 查看下这是个什么鬼

在这里插入图片描述
我们可以看到这个类继承了EventLoop,点击eventProcessLoop.start()同时看到了这个方法上面启动了二.2中我们讲到的启动了我们的线程

在这里插入图片描述

在这里插入图片描述
5。往上翻,看下是哪个方法执行了eventProcessLoop.start(),可以看到是DAGScheduler这个类
在这里插入图片描述

6.因此,我们上面是分析到,我们通过SparkContext的runJob方法-> dagScheduler.runJob->DAGScheduler的runJob中submitJob方法->eventProcessLoop.post方法将JobSubmitted(
jobId, rdd, func2, partitions.toArray, callSite, waiter,
SerializationUtils.clone(properties))这个函数放到一个名字为eventQueue队列中,但是这个队列的消费端,在DAGScheduler这个类中。因此我们下一步需要找打的创建DAGScheduler类的入口。

在我们编写代码时,我们需要创建SparkContext,通过这个类来生产RDD,SparkContext是spark的唯一通道,因此很可能在执行SparkContext 时候就已经创建好了。经过查找,果然是这样的。
因此我们猜想,其实driver在代码执行创建SparkContext的时候就已经创建好了。
在这里插入图片描述

7.上面我们已经找到消费eventQueue的地方了,接下来找下,这个被消费的eventQueue里,做了什么处理。

在这里插入图片描述

在这里插入图片描述
8。点击doOnReceive

在这里插入图片描述
在这里插入图片描述

9.我们上面传的方法是JobSubmitted 方法,因此我们点击dagScheduler.handleJobSubmitted 看下
在这里插入图片描述

我们看到有finalRDD,finalStage,说明,这个方法是划分宽窄依赖,划分stage的核心。也就是DAGScheduler的核心,stage的划分是通过我们计算流程的最后一个rdd来进行划分的。

我们以下图RDD与stage的划分跟踪这段代码
在这里插入图片描述

10.点击submitStage,其中finalStage中封装只有最后一个RDD,如下图我们可以看到submitStage这是个递归方法,
在这里插入图片描述

11.点击getMissingParentStages 方法,通过封装最后一个rdd的最后一个stage,向前推导,寻找父stage。
在这里插入图片描述

visit是匿名函数,waitingForVisit把最后一个stage放来了,第一轮循环执行步骤如下图
在这里插入图片描述

第二轮循环,
在这里插入图片描述

因此最后missing里存逻辑上放了两个宽依赖G-_F,B-A

12。我们回到submitStage 方法,轮询missing中的F和A,直到最后misssing为空,F和A轮询中执行submitMissingTasks,

在这里插入图片描述

13.点击submitMissingTasks 方法,往下看就会看到taskScheduler.submitTasks 方法。我们可以看到
传的是一组task集合
在这里插入图片描述

三、task发送
1。点击submitTasks 方法找到实现类。
在这里插入图片描述

2。我们看到最后执行 backend.reviveOffers() 我们看下backend是啥
在这里插入图片描述

3。找SchedulerBackend 的继承类CoarseGrainedSchedulerBackend,查找上面的reviveOffers 方法。

在这里插入图片描述

在这里插入图片描述
如上图,可以看到又发消息了。。

4.看下ReviveOffers是谁,如下图它继承了CoarseGrainedClusterMessage ,点进来发现没有任何用,哈哈。

在这里插入图片描述
5.然后看下CoarseGrainedSchedulerBackend 在哪里用了它。
在这里case了一下
在这里插入图片描述

6.点击makeOffers,点击launchTasks
在这里插入图片描述

7。如下图解析,已经向executor发送task了
在这里插入图片描述

四、task任务执行
1.我们需要找到executor类去找到接收task的方法大。

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值