白话Spark——DAGScheduler,TaskScheduler,SchedulerBackend模块实现机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Handoking/article/details/81122877

用最简单的话说明白一件复杂的事情也是一种成就。

这里写图片描述
Scheduler任务调度器模块作为Spark的核心部件,涉及三个重要的类
1. org.apache.spark.scheduler.DAGScheduler
2. org.apache.spark.scheduler.SchedulerBackend
3. org.apache.spark.scheduler.TaskScheduler
本文用最直白的语言说一说自己对DAGScheduler的理解。
DAGSheduler主要负责分析用户提交的应用,并将DAG进行阶段划分,每个阶段stage包括可以并行执行的多个task,这些task的执行逻辑完全相同,只是应用在不同的数据,最后将这些task提交给taskscheduler。下面分别简述这个过程的几个步骤:

1.DAGScheduler的建立

用户提交编写的sparkcontext时就创建了DAGScheduler和TaskScheduler。

2.job提交

job产生发生在RDD执行动作时,这个动作运行方法runjob,来监听job的运行情况。DAGSheduler通过内部的方法submitJob来提交,但此时的提交只是job最终提交的一小步。此时提交job并生成jobid,将job放入队列中,由DAGSheduler中的方法来依次处理。最后的提交是送给了DAGScheduler.handleJobSubmitted,这个方法会进行处理job并进行阶段划分。

3.stage划分

stage的划分是从最后往前逆推的,依宽依赖作为划分的准则,遇到宽依赖就划分出一个stage,遇到窄依赖就压入栈中。从stage到父stage以及从RDD找出依赖,均是从最后执行动作的RDD,根据依赖信息往前探寻,为了避免重复访问或者说重复运算,将访问过的RDD存入Hashset中。递归调用方法getparentStage来不断划分stage,每次划分阶段都会生成一个stageid,因为递归调用所以命名的id越往前越小,也就是说从后面先划分的stageid是最大的,越小的阶段之后提交后先被运算。以这样的步骤划分阶段,直到阶段宽依赖划分完毕或者第一个RDD被访问完成。

经过以上三个步骤,DAGScheduler将包含一组task的stage提交给TaskScheduler,当然之后还涉及到org.apache.spark.scheduler.SchedulerBackend进行资源分配等。

TaskSheduler和SchedulerBackend的实现机制

TaskScheduler任务调度:上文中已经介绍了TaskScheduler和SchedulerBackend在sparkcontext提交时就被创建,spark根据不同的资源管理方式cluster manager来创建不同的TaskScheduler,SchedulerBackend。SchedulerBackend与cluster manager资源管理器交互取得应用被分配的资源。TaskSheduler在不同的job之间调度,同时接收被分配的资源,之后由他来给每一个Task分配资源。
Task的提交过程:
DAGScheduler最终的提交给TaskScheduler的是包含一组task的taskset,之前说过这个taskset和stage是一样的。在提交task的过程中每个taskset都被送到一个taskmanager中,taskmanager会根据就近原则来给task分配资源,但taskmanager要根据一定的调度策略来进行调度然后再将task分别分配给不同的executor进行处理。看图可以理解更明白:
这里写图片描述
这是两种调度策略之一的FIFO就是先进先出的队列规则,根据之前说过的stageId以及taskid,先处理编号小的任务。另一种是调度策略是FAIR,称作公平调度,见下图
这里写图片描述
可以看出这种调度规则不仅是将pool按照确定调度顺序,同时将pool内部的tasksetmanager用同样的方法进行确定调度顺序。rootpool可以简单地理解为树根节点,pool为叶子结点。
分配好资源,根据executor的列表,产生了TaskDescription,它包含了task和executor的对应关系,如taskid和executorid,以及task的环境依赖等。这几个操作均在resourceoffer方法中实现,因此这是个非常重要的方法。
task在executor上执行完成后,executor通过心跳向Driver发送处理状态更新,将此task标记为finish。同时executor处理后的结果回执给Driver,Driver根据结果的大小不同来选择不同的方式处理。大于1G的结果直接舍弃;能留下200kb的自由空间的结果存入blockmanager;其余的直接传回Driver。
容错机制
失败的任务由tasksetmanager来负责,它根据失败的不同和情况来进行不同的处理。对于小于提交次数阈值的任务进行再次提交,当然并不是所有的小于阈值的任务都可以提交。因调度出错导致task失败的情况,就算再次提交也是失败,所以这样的task被标记为待调度。

猜你喜欢

转载自blog.csdn.net/Handoking/article/details/81122877
今日推荐