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

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

你可能感兴趣的:(spark源码分析,spark)