spark源码阅读-动作操作stage的划分和job的提交

spark算是一个比较用途广泛的一个框架,dan是要想真正了解其框架还是要从其源码开始
第一步 准备spark的源码包,要有一定的scala基础 saprk源码下载
[http://spark.apache.org/downloads.html]
1.打开spark源码 执行一个动作操作 collect()开始追踪源码
在这里插入图片描述
按住crtal单击collect进入 这里传入的参数是this->最后执行的一个rdd也就是动作操作的rdd,还有一个只想的函数
在这里插入图片描述
再继续向下开始追踪runJob 这里返回的是一个数组 前面的两个参数居室上面传入的参数,这里传入分区,每一个分区分别计算结果
在这里插入图片描述
继续追踪runJob
在这里插入图片描述
追踪到这里我们可以假设 你有3个分区 你就要生成一个长度为3的数组 第一个分区产生的结果根据索引存到该数组里面 res其实就是经过func在一个分区上面运行的结果
在这里插入图片描述接着追踪runJob 这一步及其重要 起到乘上启下的作用 我们可以看到最好一个rdd是调用dagScheduler调度器中的runJob
在这里插入图片描述接下来继续看dagScheduler中的runJob函数 这里利用submitJob()来提交作业 ,这里还另外启用的一个线程 就像是kafka里面的 Future一样进行异步的调用来监控作业提交的状态和等待运行的结果 waiter.completionFuture的操作 所以我们要接着继续追踪submitJob提交任务
在这里插入图片描述这一段及其重要,其中waiter等待任务提交的结果,其中将任务包装好放到一个JobSubmitted的样例类里面,这里包装的目的其实就是为了方便进行网络传输的,还有一个重点就是DagScheduler调度器是在Driver端运行,现在我要到Master端的Excetur里面去运行,我们所收支的一种调用方式就是RPC远程调用,但是这里为了提高性能用的是一个队列,可以关注eventProcessLoop这个队列的实现在这里插入图片描述下一步就有必要了解一下这个队列的具体原理,我们进入post方法,测试进入的是EventLoop的类 ,这里我给一个超链接,可以自己去了解这个队列的运行原理添加链接描述
在这里插入图片描述然后我们要关注EventLoop里面其实帮我们启动来一个线程,但是EventLoop是一个抽象类,所以我们接下来要到它的子类里面去寻找onRceive的实现,此时回想前面的代码句知道,其实就是DAGSchedulerEventProcessLoop,这样的话我们可以到这个类里面去找onReceive的方法
在这里插入图片描述从这个代码可以看出 driver端提交过来的数据来进行模式匹配 JobSubmitted事件所以执行这段在这里插入图片描述
现在我们已经分析到将任务提交到Dag调度器了 这个任务里面有rdd的信息和各个依赖,所以我们应该再利用Dag调度器对你的RDD来进行Stage的划分,这里面重点关注截图的那两段截图,一段是用递归创建Stage另一段是提交Stage在这里插入图片描述在这里插入图片描述接下来就需要了解创建这个Stage是如何创建的,重点关注parents的值 ,这里是创建或者获取该RDD的Shuffer依赖关系而划分Stage,其实在Spark里面中的Rdd中有两种类型,从源码中的可以看到,非动作RDD其实是MapPartitionsRDD***,而动作操作的RDD其实ShuffledRDD***,其实也就是宽依赖和窄依赖,从源码的阅读就可以很清晰的得出,分区数,和分区器相同就是宽依赖
回到这里来 找到这个stage之后就创建一个jobid,创建stage在这里插入图片描述在这里插入图片描述我们继续聚焦getOrCreateParentStages是如何找shufferRDD的实现,这里是先执行前面
getShuffleDependencies
找到所有的窄依赖,然后循环这些依赖执行
getOrCreateShuffleMapStage**这个划分Stage
在这里插入图片描述在这里插入图片描述接下来就是划分找到shufferRDD的核心逻辑代码了,现在假设各个RDD的依赖关系如上图所示,这里主要解释一下为什么要用栈来存储RDD,其实是很好理解的,因为我们传进来的是最后面的RDD也就是动作操作,但是它前面执行来很多map操作都已经形成了依赖,所以存储顺序是 G->B->A,但是,但是执行顺序应该是A->B->G所以要用栈结构,仔细研读代码可以发现,执行这断代码可以返回一个多个ShufferRDD在这里插入图片描述好了上面这一步就获取动作操作RDD两个分支的第一个Shuffer操作的RDD来,此时回到上一步循环这两个ShufferRDD来创建stage,先是依赖A进来 进行模式匹配 看是不是已经建好stage了,如果已经建好那就直接返回这个stage,如果没有这个stage,那么就要走getMissingAncestorShuffleDependencies这个函数,而这个函数的作用是获取该rdd的祖先或者是下一个shufferRDD,而且返回的是一个栈结构,这里创建的ShufferMapStage公用一个firstJobId,最后面将自己的这个rdd创建返回stage就划分好了
在这里插入图片描述
现在已经完成了stage的划分 并将消息都存存到一个队列了,现在就只需要提交stage任务了
在这里插入图片描述接下来句是要分析submitMissingTasks这个函数了 将任务提交到master端的Excetur去运行,底层使用netty来进行通讯,有兴趣的小伙伴可以继续深入向下进行分析。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值