【Spark2.0源码学习】-9.Job提交与Task的拆分

.png)
- Code:指的用户编写的代码
- RDD:弹性分布式数据集,用户编码根据SparkContext与RDD的api能够很好的将Code转化为RDD数据结构(下文将做转化细节介绍)
- DAGScheduler:有向无环图调度器,将RDD封装为JobSubmitted对象存入EventLoop(实现类DAGSchedulerEventProcessLoop)队列中
- EventLoop: 定时扫描未处理JobSubmitted对象,将JobSubmitted对象提交给DAGScheduler
- DAGScheduler:针对于JobSubmitted进行处理,最终将RDD转化为执行TaskSet,并将TaskSet提交至TaskScheduler
- TaskScheduler: 根据TaskSet创建TaskSetManager对象存入SchedulableBuilder的数据池(Pool)中,并调用DriverEndpoint唤起消费(ReviveOffers)操作
- DriverEndpoint:接受ReviveOffers指令后将TaskSet中的Tasks根据相关规则均匀分配给Executor
- Executor:启动一个TaskRunner执行一个Task
.png)

- ExecuteEnv(执行环境 )
- 这里可以是通过spark-submit提交的MainClass,也可以是spark-shell脚本
- MainClass : 代码中必定会创建或者获取一个SparkContext
- spark-shell:默认会创建一个SparkContext
- RDD(弹性分布式数据集)
- create:可以直接创建(如:sc.parallelize(1 until n, slices) ),也可以在其他地方读取(如:sc.textFile("README.md"))等
- transformation:rdd提供了一组api可以进行对已有RDD进行反复封装成为新的RDD,这里采用的是装饰者设计模式,下面为部分装饰器类图
.png)

- action:当调用RDD的action类操作方法时(collect、reduce、lookup、save ),这触发DAGScheduler的Job提交
- DAGScheduler:创建一个名为JobSubmitted的消息至DAGSchedulerEventProcessLoop阻塞消息队列(LinkedBlockingDeque)中
- DAGSchedulerEventProcessLoop:启动名为【dag-scheduler-event-loop】的线程实时消费消息队列
- 【dag-scheduler-event-loop】处理完成后回调JobWaiter
- DAGScheduler:打印Job执行结果
- JobSubmitted:相关代码如下(其中jobId为DAGScheduler全局递增Id):
eventProcessLoop.post(JobSubmitted(
jobId, rdd, func2, partitions.toArray, callSite, waiter,
SerializationUtils.clone(properties)))
- 最终示例:

.png)


- DAGSchedulerEventProcessLoop中,线程【dag-scheduler-event-loop】处理到JobSubmitted
- 调用DAGScheduler进行handleJobSubmitted
- 首先根据RDD依赖关系依次创建Stage族,Stage分为ShuffleMapStage,ResultStage两类

.png)
- 更新jobId与StageId关系Map
- 创建ActiveJob,调用LiveListenerBug,发送SparkListenerJobStart指令
- 找到最上层Stage进行提交,下层Stage存入waitingStage中待后续处理
- 调用OutputCommitCoordinator进行stageStart()处理
- 调用LiveListenerBug, 发送 SparkListenerStageSubmitted指令
- 调用SparkContext的broadcast方法获取Broadcast对象
- 根据Stage类型创建对应多个Task,一个Stage根据findMissingPartitions分为多个对应的Task,Task分为ShuffleMapTask,ResultTask

- 将Task封装为TaskSet,调用TaskScheduler.submitTasks(taskSet)进行Task调度,关键代码如下:
- 首先根据RDD依赖关系依次创建Stage族,Stage分为ShuffleMapStage,ResultStage两类
taskScheduler.submitTasks(new TaskSet(
tasks.toArray, stage.id, stage.latestInfo.attemptId, jobId, properties))
.png)

- DAGSheduler将TaskSet提交给TaskScheduler的实现类,这里是TaskChedulerImpl
- TaskSchedulerImpl创建一个TaskSetManager管理TaskSet,关键代码如下:
new TaskSetManager(this, taskSet, maxTaskFailures, blacklistTrackerOpt)
- 同时将TaskSetManager添加SchedduableBuilder的任务池Poll中
- 调用SchedulerBackend的实现类进行reviveOffers,这里是standlone模式的实现类StandaloneSchedulerBackend
- SchedulerBackend发送ReviveOffers指令至DriverEndpoint


- 首先根据executorDataMap缓存信息得到可用的Executor资源信息(WorkerOffer),关键代码如下
val activeExecutors = executorDataMap.filterKeys(executorIsAlive)
val workOffers = activeExecutors.map { case (id, executorData) =>
new WorkerOffer(id, executorData.executorHost, executorData.freeCores)
}.toIndexedSeq
- 接着调用TaskScheduler进行资源匹配,方法定义如下:
def resourceOffers(offers: IndexedSeq[WorkerOffer]): Seq[Seq[TaskDescription]] = synchronized {..}
- 将WorkerOffer资源打乱(val shuffledOffers = Random.shuffle(offers))
- 将Poo中待处理的TaskSetManager取出(val sortedTaskSets = rootPool.getSortedTaskSetQueue),
- 并循环处理sortedTaskSets并与shuffledOffers循环匹配,如果shuffledOffers(i)有足够的Cpu资源( if (availableCpus(i) >= CPUS_PER_TASK) ),调用TaskSetManager创建TaskDescription对象(taskSet.resourceOffer(execId, host, maxLocality)),最终创建了多个TaskDescription,TaskDescription定义如下:
new TaskDescription(
taskId,
attemptNum,
execId,
taskName,
index,
sched.sc.addedFiles,
sched.sc.addedJars,
task.localProperties,
serializedTask)
- 如果TaskDescriptions不为空,循环TaskDescriptions,序列化TaskDescription对象,并向ExecutorEndpoint发送LaunchTask指令,关键代码如下:
for (task <- taskDescriptions.flatten) {
val serializedTask = TaskDescription.encode(task)
val executorData = executorDataMap(task.executorId)
executorData.freeCores -= scheduler.CPUS_PER_TASK
executorData.executorEndpoint.send(LaunchTask(new SerializableBuffer(serializedTask)))
}
【Spark2.0源码学习】-9.Job提交与Task的拆分的更多相关文章
- 【Spark2.0源码学习】-1.概述
Spark作为当前主流的分布式计算框架,其高效性.通用性.易用性使其得到广泛的关注,本系列博客不会介绍其原理.安装与使用相关知识,将会从源码角度进行深度分析,理解其背后的设计精髓,以便后续 ...
- spark2.0源码学习
[Spark2.0源码学习]-1.概述 [Spark2.0源码学习]-2.一切从脚本说起 [Spark2.0源码学习]-3.Endpoint模型介绍 [Spark2.0源码学习]-4.Master启动 ...
- 【Spark2.0源码学习】-2.一切从脚本说起
从脚本说起 在看源码之前,我们一般会看相关脚本了解其初始化信息以及Bootstrap类,Spark也不例外,而Spark我们启动三端使用的脚本如下: %SPARK_HOME%/sbin/st ...
- 【Spark2.0源码学习】-3.Endpoint模型介绍
Spark作为分布式计算框架,多个节点的设计与相互通信模式是其重要的组成部分. 一.组件概览 对源码分析,对于设计思路理解如下: RpcEndpoint: ...
- 【Spark2.0源码学习】-4.Master启动
Master作为Endpoint的具体实例,下面我们介绍一下Master启动以及OnStart指令后的相关工作 一.脚本概览 下面是一个举例: /opt/jdk1..0_79/ ...
- 【Spark2.0源码学习】-5.Worker启动
Worker作为Endpoint的具体实例,下面我们介绍一下Worker启动以及OnStart指令后的额外工作 一.脚本概览 下面是一个举例: /opt/jdk1..0_79/ ...
- 【Spark2.0源码学习】-6.Client启动
Client作为Endpoint的具体实例,下面我们介绍一下Client启动以及OnStart指令后的额外工作 一.脚本概览 下面是一个举例: /opt/jdk1..0_79/bin/jav ...
- 【Spark2.0源码学习】-10.Task执行与回馈
通过上一节内容,DriverEndpoint最终生成多个可执行的TaskDescription对象,并向各个ExecutorEndpoint发送LaunchTask指令,本节内容将关注Exe ...
- 【Spark2.0源码学习】-7.Driver与DriverRunner
承接上一节内容,Client向Master发起RequestSubmitDriver请求,Master将DriverInfo添加待调度列表中(waitingDrivers),下面针对于Dri ...
随机推荐
- spring项目log4j使用入门
log4j是Java开发中经常使用的一个日志框架,功能强大,配置灵活,基本上可以满足项目开发中对日志功能的大部分需求.我前后经历了四五个项目,采用的日志框架都是log4j,这也反应了log4j受欢迎的 ...
- 浩哥解析MyBatis源码(九)——Type类型模块之类型处理器注册器(TypeHandlerRegistry)
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6709157.html 1.回顾 上一篇研究的是类型别名注册器TypeAliasRegist ...
- 关于binary log一点总结[转]
阅读目录(Content) 1 what's binary log 2 Binary Logging Options and Variables 2.1 基础参数 3 Binary Logging F ...
- js:通过正则匹配获取页面的url中的参数
简介:获取页面参数 原生js: //通过正则匹配获取当前页面的url中的参数 function getUrlParam(name){ var reg = new RegExp("(^|&am ...
- STM32学习笔记(三)——外部中断的使用
开发板芯片:STM32F407ZGT6 硬件连接:PE3-KEY1 一.STM32F4的中断介绍 STM32F4的每个IO都可以作为外部中断输入,很强大的功能吧!以前学习的51只有两个外部中断. ST ...
- Java异常分类及处理
1.Throwable是所有异常的根(java.lang.Throwable)2.Error是错误(java.lang.Error) 当程序发生不可控的错误时,程序会报错,Error及其子类的对象不应 ...
- linux C/C++ 日志打印函数
//宏定义日志文件名 #define PROCESSNAME "log_filename" //当日志文件大于5M时,会删除该文件,该接口使用方法 参照printfvoid Wr ...
- 新建Android项目,会出现两个项目一个是自己创建的项目,另一个是“appcompat_v7”项目,这是怎么回事呢?该怎么解决呢?
做Android开发的朋友最近会发现,更新ADT至22.6.0版本之后,创建新的安装项目,会出现appcompat_v7的内容.并且是创建一个新的内容就会出现.这到底是怎么回事呢?原来appcompa ...
- hdu5145 NPY and girls
人生中第一道莫队,本来以为是一道水题的.. 首先这题只有区间查询,没有修改操作,使用莫队比较明显,但统计答案有点麻烦.. 根据题意,在n个人里选m个不相同种类的人,设第i种人数量为ai,总方案为c(n ...
- DirectFB 之 通过多Window实现多元素处理
图像 设计 采用多window的方式实现显示,因为每个window可以独立的属性,比如刷新频率,也是我们最关注的 示例 /*************************************** ...