spark 源码分析之十九 -- Stage的提交
引言
上篇 spark 源码分析之十九 -- DAG的生成和Stage的划分 中,主要介绍了下图中的前两个阶段DAG的构建和Stage的划分。
本篇文章主要剖析,Stage是如何提交的。
rdd的依赖关系构成了DAG,DAGScheduler根据shuffle依赖关系将DAG图划分为一个一个小的stage。具体可以看 spark 源码分析之十九 -- DAG的生成和Stage的划分 做进一步了解。

紧接上篇文章
上篇文章中,DAGScheduler的handleJobSubmitted方法我们只剖析了stage的生成部分,下面我们看一下stage的提交部分源码。

提交Stage的思路
首先构造ActiveJob对象,其次清除缓存的block location信息,然后记录jobId和job对象的映射关系到jobIdToActiveJob map集合中,并且将该jobId记录到活动的job集合中。
获取到Job所有的stage的唯一标识,并且根据唯一标识来获取stage对象,并且调用其lastestInfo方法获取其StageInfo对象。
然后进一步封装成 SparkListenerJobStart 事件对象,并post到 listenerBus中,listenerBus 是一个 LiveListenerBus 对象,其内部封装了四个消息队列组成的集合,具体可以看 spark 源码分析之三 -- LiveListenerBus介绍 文章做进一步了解。
最后调用submitStage 方法执行Stage的提交。
先来看一下ActiveJob的说明。
ActiveJob
类说明
A running job in the DAGScheduler. Jobs can be of two types: a result job, which computes a ResultStage to execute an action, or a map-stage job, which computes the map outputs for a ShuffleMapStage before any downstream stages are submitted. The latter is used for adaptive query planning, to look at map output statistics before submitting later stages. We distinguish between these two types of jobs using the finalStage field of this class. Jobs are only tracked for "leaf" stages that clients directly submitted, through DAGScheduler's submitJob or submitMapStage methods. However, either type of job may cause the execution of other earlier stages (for RDDs in the DAG it depends on), and multiple jobs may share some of these previous stages. These dependencies are managed inside DAGScheduler.
它代表了正运行在DAGScheduler中的一个job,job有两种类型:result job,其通过计算一个ResultStage来执行一个action操作;map-stage job,它在下游的stage提交之前,为ShuffleMapStage计算map的输出。
构造方法

finalStages是这个job的最后一个stage。
提交Stage前的准备
直接先来看submitStage方法,如下:

思路: 首先先获取可能丢失的父stage信息,如果该stage的父stage被遗漏了,则递归调用查看其爷爷stage是否被遗漏。
查找遗漏父Stage
getMissingParentStages方法如下:

思路:不断创建父stage,可以看上篇文章 spark 源码分析之十九 -- DAG的生成和Stage的划分 做进一步了解。
提交Stage
submitMissingTasks方法过于长,为方便分析,按功能大致分为如下部分:
获取Stage需要计算的partition信息

org.apache.spark.scheduler.ResultStage#findMissingPartitions 方法如下:

org.apache.spark.scheduler.ShuffleMapStage#findMissingPartitions 方法如下:

org.apache.spark.MapOutputTrackerMaster#findMissingPartitions 方法如下:

将stage和分区记录到OutputCommitCoordinator中

OutputCommitCoordinator 的 stageStart实现如下:

本质上就是把它放入到一个map中了。
获取分区的优先位置

思路:根据stage的RDD和分区id获取到其rdd中的分区的优先位置。
下面看一下 getPreferredLocs 方法:

注释中说到,它是线程安全的,下面看一下,它是如何实现的,即 getPrefferredLocsInternal 方法。

这个方法中提到四种情况:
1. 如果之前获取到过,那么直接返回Nil即可。
2. 如果之前已经缓存在内存中,直接从缓存的内存句柄中取出返回即可。
3. 如果RDD对应的是HDFS输入的文件等,则使用RDD记录的优先位置。
4. 如果上述三种情况都不满足,且是narrowDependency,则调用该方法,获取子RDDpartition对应的父RDD的partition的优先位置。
下面仔细说一下中间两种情况。
从缓存中取
getCacheLocs 方法如下:

思路:先查看rdd的存储级别,如果没有存储级别,则直接返回Nil,否则根据RDD和分区id组成BlockId集合,请求存储系统中的BlockManager来获取block的位置,然后转换为TaskLocation信息返回。
获取RDD的优先位置
RDD的 preferredLocations 方法如下:

思路:先从checkpoint中找,如果checkpoint中没有,则返回默认的为Nil。
返回对象是TaskLocation对象,做一下简单的说明。
TaskLocation
类说明
A location where a task should run. This can either be a host or a (host, executorID) pair. In the latter case, we will prefer to launch the task on that executorID, but our next level of preference will be executors on the same host if this is not possible.
它有三个子类,如下:

这三个类定义如下:

很简单,不做过多说明。
TaskLocation伴随对象如下,现在用的方法是第二种 apply 方法:

创建新的StageInfo
对应方法如下:

org.apache.spark.scheduler.Stage#makeNewStageAttempt 方法如下:

很简单,主要是调用了StageInfo的fromStage方法。
先来看Stage类。
StageInfo
StageInfo封装了关于Stage的一些信息,用于调度和SparkListener传递stage信息。
其伴生对象如下:

广播要执行task函数
对应源码如下:

通过broadcast机制,将数据广播到spark集群中的driver和各个executor中。关于broadcast的实现细节,可以查看 spark 源码分析之十四 -- broadcast 是如何实现的?做进一步了解。
生成Task集合

根据stage的类型生成不同的类型Task。关于过多Task 的内容,在阶段四进行剖析。
TaskScheduler提交TaskSet
对应代码如下:

其中taskScheduler是 TaskSchedulerImpl,它是TaskScheduler的唯一子类实现。它负责task的调度。
org.apache.spark.scheduler.TaskSchedulerImpl#submitTasks方法实现如下:

其中 createTaskSetManager 方法如下:

关于更多TaskSetManager的内容,将在阶段四进行剖析。
backend是一个 SchedulerBackend 实例。在SparkContetx的初始化过程中调用 createTaskScheduler 初始化 backend,具体可以看 spark 源码分析之四 -- TaskScheduler的创建和启动过程 做深入了解。
在yarn 模式下,它有两个实现yarn-client 模式下的 org.apache.spark.scheduler.cluster.YarnClientSchedulerBackend实现 和 yarn-cluster 模式下的 org.apache.spark.scheduler.cluster.YarnClusterSchedulerBackend 实现。
这两个类在spark 项目的 resource-managers 目录下的 yarn 目录下定义实现,当然它也支持 kubernetes 和 mesos,不做过多说明。
这两个类的继承关系如下:

org.apache.spark.scheduler.cluster.CoarseGrainedSchedulerBackend#reviveOffers 实现如下:

发送ReviveOffers 请求给driver。
driver端的 CoarseGrainedSchedulerBackend 的 receive 方法有如下事件处理分支:

其内部经过一系列RPC过程,关于 RPC 可以看 spark 源码分析之十二--Spark RPC剖析之Spark RPC总结 做进一步了解。
即会调用driver端的makeOffsers方法,如下:

总结
本篇文章剖析了从DAGScheduler生成的Stage是如何被提交给TaskScheduler,以及TaskScheduler是如何把TaskSet提交给ResourceManager的。
下面就是task的运行部分了,下篇文章对其做详细介绍。跟task执行关系很密切的TaskSchedulerBackend、Task等内容,也将在下篇文章做更详细的说明。
spark 源码分析之十九 -- Stage的提交的更多相关文章
- spark 源码分析之十九 -- DAG的生成和Stage的划分
上篇文章 spark 源码分析之十八 -- Spark存储体系剖析 重点剖析了 Spark的存储体系.从本篇文章开始,剖析Spark作业的调度和计算体系. 在说DAG之前,先简单说一下RDD. 对RD ...
- spark 源码分析之十二 -- Spark内置RPC机制剖析之八Spark RPC总结
在spark 源码分析之五 -- Spark内置RPC机制剖析之一创建NettyRpcEnv中,剖析了NettyRpcEnv的创建过程. Dispatcher.NettyStreamManager.T ...
- spark 源码分析之十八 -- Spark存储体系剖析
本篇文章主要剖析BlockManager相关的类以及总结Spark底层存储体系. 总述 先看 BlockManager相关类之间的关系如下: 我们从NettyRpcEnv 开始,做一下简单说明. Ne ...
- spark 源码分析之十五 -- Spark内存管理剖析
本篇文章主要剖析Spark的内存管理体系. 在上篇文章 spark 源码分析之十四 -- broadcast 是如何实现的?中对存储相关的内容没有做过多的剖析,下面计划先剖析Spark的内存机制,进而 ...
- spark 源码分析之十六 -- Spark内存存储剖析
上篇spark 源码分析之十五 -- Spark内存管理剖析 讲解了Spark的内存管理机制,主要是MemoryManager的内容.跟Spark的内存管理机制最密切相关的就是内存存储,本篇文章主要介 ...
- spark 源码分析之十--Spark RPC剖析之TransportResponseHandler、TransportRequestHandler和TransportChannelHandler剖析
spark 源码分析之十--Spark RPC剖析之TransportResponseHandler.TransportRequestHandler和TransportChannelHandler剖析 ...
- ABP源码分析二十九:ABP.MongoDb
这个Module通过建立一个MongoDbRepositoryBase<TEntity> 基类,封装了对MongoDb数据库的操作. 这个module通过引用MongoDB.Driver, ...
- ABP源码分析三十九:ABP.Hangfire
ABP对HangFire的集成主要是通过实现IBackgroundJobManager接口的HangfireBackgroundJobManager类完成的. HangfireBackgroundJo ...
- Vue.js 源码分析(二十九) 高级应用 transition-group组件 详解
对于过度动画如果要同时渲染整个列表时,可以使用transition-group组件. transition-group组件的props和transition组件类似,不同点是transition-gr ...
随机推荐
- Linux实现彩色提示符
更改用户目录下的.bashrc 加入: export PS1='\[\e[33m\][\u@\h:\W]\$ \[\e[m\]' 例如: # .bashrc # User specific alias ...
- SilverlightMVVM模式中的数据校验
silverlight的数据校验大体分成3种类型: 数据是非必填的但是需要满足相应数据格式的 数据是必填的且可能需要进行数据格式校验的 其他(如数据的联动校验) 以下的数据校验方式针对第二种: 在相应 ...
- Terminator快捷键
窗口相关 窗口开关 上下开新窗口 Ctrl+Shift+O垂直开新窗口 Ctrl+Shift+E关闭当前窗口 Ctrl+Shift+W 改变当前激活窗口 逆时针改变当前窗口 Ctrl+Sh ...
- 八大排序算法 JAVA实现 亲自测试 可用!
今天很高兴 终于系统的实现了八大排序算法!不说了 直接上代码 !代码都是自己敲的, 亲测可用没有问题! 另:说一下什么是八大排序算法: 插入排序 希尔排序 选择排序 堆排序 冒泡排序 快速排序 归并排 ...
- 反向代理在APP通过无线路由接入3G/4G时的特殊作用
由于某些需求,要临时搭建局域网络,给小范围内大量移动客户端提供特定的网络服务,这样的服务通常包含常见的HTTP服务.数据文件下载服务.RESTFul接口服务等.市面常见的非企业级WIFI路由器能够承受 ...
- spark streaming 接收kafka消息之三 -- kafka broker 如何处理 fetch 请求
首先看一下 KafkaServer 这个类的声明: Represents the lifecycle of a single Kafka broker. Handles all functionali ...
- 『 效率工具 』Spring Boot版的轻量级代码生成器,减少70%以上的开发任务
一. 前言 之前很着迷于代码自动生成,减少写重复代码的工作量.网络上也搜索了很久,有基于插件的,有GUI的.但其配置和学习成本都比较高,都不是很如我意. 本想自己用SpringBoot写一个,在收集相 ...
- Hexo+NexT(一):在Windows下安装Hexo+NexT及搭建博客
阅读本篇之前,假定读者已经有了Node.js的基础,如需要补充Node.js知识的,请自行百度. Hexo是在Node.js框架下的一个项目,利用Node.js提供的强大功能,完成从Markdown到 ...
- java源码解析之String类(一)
String是我们接触最多的类,无论是学习中还是工作中,基本每天都会和字符串打交道,从字符串本身的各种拼接.切片.变形,再到和其他基本数据类型的转换,几乎无时无刻都在使用它,今天就让我们揭开Strin ...
- Spring ——表达式语言 Spring Expression Language (转载)
目录 SpEL简介与功能特性 一.为什么需要Spring表达式语言 二.SpEL表达式Hello World! 三.SpEL表达式 3.1.文字表达式 3.2.SPEL语言特性 3.2.1.属性 3. ...