Spark分析之TaskScheduler
TaskScheduler概述:
TaskScheduler是一个可插拔任务调度接口,通过不同的SchedulerBackend进行任务的调度。主要功能如下:
1、一个TaskScheduler只为一个SparkContext服务,接收DAGScheduler提交过来的一组组的TaskSet;
2、TaskScheduler将task提交到集群中并执行,如果其中某个Task执行失败则重试之;TaskScheduler将TaskSet对应的执行结果返回才DAGScheduler;
3、TaskScheduler处理straggle任务(比如:100个任务运行,其中99个任务快,1个任务慢,需要在另外一个节点上开启一个相同的任务来运行,谁先完成取用谁);
4、遇到shuffle输出丢失则汇报给DAGScheduler;
5、为每个TaskSet维护一个TaskSetManager追踪本地性(resourceOffer-->findTask)及错误信息;
TaskSet.scala
private[spark] class TaskSet(
val tasks: Array[Task[_]],
val stageId: Int, //该TaskSet对应哪个stage
val attempt: Int,
val priority: Int,
val properties: Properties) {
val id: String = stageId + "." + attempt
}
Task分析:
1、Task是Executor中的执行单元;不像MR中,这里并没有map/reduce任务;
2、Task处理数据常见的两个来源:外部存储以及shuffle数据;
3、Task可以运行在集群中的任意一个节点上(最差的情况就是集群节点之间数据的传输);
4、Task可以使用缓存但是已经被置换出来的数据;
5、为了容错,会将shuffle输出写到磁盘或者内存中;
Spark中有两种Task:
1、ShuffleMapTASK:输出的数据作为后续操作的来源
A ShuffleMapTask divides the elements of an RDD into multiple buckets (based on a partitioner);
2、ResultTask:输出的是结果
A task that sends back the output to the driver application.
源码执行流程:TaskSchedulerImpl.scala
override def submitTasks(taskSet: TaskSet) {
val tasks = taskSet.tasks
logInfo("Adding task set " + taskSet.id + " with " + tasks.length + " tasks")
this.synchronized {
val manager = new TaskSetManager(this, taskSet, maxTaskFailures) //每个taskset被封装成一个TaskSetManager
activeTaskSets(taskSet.id) = manager
schedulableBuilder.addTaskSetManager(manager, manager.taskSet.properties) //将tasksetmanager添加到调度器中,FIFO/Fair
......
hasReceivedTask = true
}
backend.reviveOffers() //请求资源执行task,backend是SchedulerBackend,向DriverActor发送ReviveOffers的请求
}
CoarseGrainedSchedulerBackend.scala
override def reviveOffers() {
driverActor ! ReviveOffers
}
case ReviveOffers =>
makeOffers()
def makeOffers() { //启动tasks
launchTasks(scheduler.resourceOffers(
executorHost.toArray.map {case (id, host) => new WorkerOffer(id, host, freeCores(id))}))
}
TaskSchedulerImpl.scala
//从FIFO或者Fair调度器哪里获得拍戏后的TaskSetManager
def resourceOffers(offers: Seq[WorkerOffer]): Seq[Seq[TaskDescription]] = synchronized {
SparkEnv.set(sc.env)
.....
// Randomly shuffle offers to avoid always placing tasks on the same set of workers.
val shuffledOffers = Random.shuffle(offers)
// Build a list of tasks to assign to each worker.
val tasks = shuffledOffers.map(o => new ArrayBuffer[TaskDescription](o.cores))
val availableCpus = shuffledOffers.map(o => o.cores).toArray
val sortedTaskSets = rootPool.getSortedTaskSetQueue
// Take each TaskSet in our scheduling order, and then offer it each node in increasing order
// of locality levels so that it gets a chance to launch local tasks on all of them.
var launchedTask = false
for (taskSet <- sortedTaskSets; maxLocality <- TaskLocality.values) {
do {
launchedTask = false
for (i <- 0 until shuffledOffers.size) {
val execId = shuffledOffers(i).executorId
val host = shuffledOffers(i).host
if (availableCpus(i) >= CPUS_PER_TASK) {
for (task <- taskSet.resourceOffer(execId, host, maxLocality)) { //考虑locality等因素来确定task的信息
...
launchedTask = true
}
}
}
} while (launchedTask)
}
if (tasks.size > 0) {
hasLaunchedTask = true
}
return tasks
}
TaskSetManager.scala
// Respond to an offer of a single executor from the scheduler by finding a task
resourceOffer{
findTask(execId, host, allowedLocality) match { //找到合适的可本地性的任务
......
}
}
CoarseGrainedSchedulerBackend.scala
// Launch tasks returned by a set of resource offers
def launchTasks(tasks: Seq[Seq[TaskDescription]]) {
for (task <- tasks.flatten) {
val serializedTask = ser.serialize(task) //序列化每个task
if (serializedTask.limit >= akkaFrameSize - AkkaUtils.reservedSizeBytes) { //task序列化后的大小超过指定的大小就中断执行
taskSet.abort(msg)
}else{
//向CoarseGrainedExecutorBackend发送启动任务的请
executorActor(task.executorId) ! LaunchTask(new SerializableBuffer(serializedTask)
}
}
} CoarseGrainedExecutorBackend.scala
case LaunchTask(data) =>
if(executor == null){} //一个 CoarseGrainedExecutorBackend 进程有且仅有一个executor对象。
val taskDesc = ser.deserialize[TaskDescription](data.value) //执行之前需要反序列化,因为在提交任务时将任务做的序列化操作
executor.launchTask(this, taskDesc.taskId, taskDesc.serializedTask)
} Executor.scala
val threadPool = Utils.newDaemonCachedThreadPool("Executor task launch worker")
def launchTask(context: ExecutorBackend, taskId: Long, serializedTask: ByteBuffer) {
val tr = new TaskRunner(context, taskId, serializedTask) //serializedTask:任务都是需要序列化的
runningTasks.put(taskId, tr)
threadPool.execute(tr) //提交到executor执行
}
Spark分析之TaskScheduler的更多相关文章
- 使用Spark分析拉勾网招聘信息(一):准备工作
本系列专属github地址:https://github.com/ios122/spark_lagou 前言 我觉得如果动笔,就应该努力地把要说的东西表达清楚.今后一段时间,尝试下系列博客文章.简单说 ...
- [大数据从入门到放弃系列教程]第一个spark分析程序
[大数据从入门到放弃系列教程]第一个spark分析程序 原文链接:http://www.cnblogs.com/blog5277/p/8580007.html 原文作者:博客园--曲高终和寡 **** ...
- Spark Scheduler模块源码分析之TaskScheduler和SchedulerBackend
本文是Scheduler模块源码分析的第二篇,第一篇Spark Scheduler模块源码分析之DAGScheduler主要分析了DAGScheduler.本文接下来结合Spark-1.6.0的源码继 ...
- Spark Core Runtime分析: DAGScheduler, TaskScheduler, SchedulerBackend
Spark Runtime里的主要层次分析,梳理Runtime组件和运行流程, DAGScheduler Job=多个stage,Stage=多个同种task, Task分为ShuffleMapTas ...
- spark 源码分析之四 -- TaskScheduler的创建和启动过程
在 spark 源码分析之二 -- SparkContext 的初始化过程 中,第 14 步 和 16 步分别描述了 TaskScheduler的 初始化 和 启动过程. 话分两头,先说 TaskSc ...
- Spark分析之Job Scheduling Process
经过前面文章的SparkContext.DAGScheduler.TaskScheduler分析,再从总体上了解Spark Job的调度流程 1.SparkContext将job的RDD DAG图提交 ...
- Spark分析之SparkContext启动过程分析
SparkContext作为整个Spark的入口,不管是spark.sparkstreaming.spark sql都需要首先创建一个SparkContext对象,然后基于这个SparkContext ...
- Spark分析之DAGScheduler
DAGScheduler概述:是一个面向Stage层面的调度器: 主要入参有: dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, ...
- 使用Spark分析拉勾网招聘信息(四): 几个常用的脚本与图片分析结果
概述 前一篇文章,已经介绍了BMR的基础用法,再结合Spark和Scala的文档,我想应该是可以开始你的数据分析之路的.这一篇文章,着重进行一些简单的思路上的引导和分析.如果你分析招聘数据时,卡在了某 ...
随机推荐
- css中的单位px,em和rem的区别
一.px: px就是像素,用px设置字体大小的时候会比较精确,但是有时候我们会使用不同屏幕尺寸去浏览网页.当页面相应的扩大或者缩小的时候,页面的字体大小就会出现过小或者过大.由于这种问题,就提出了使用 ...
- TouchJSON的简单使用
TouchJSON是OC转换JSON的一个第三方类库,使用简单.在GitHub上可以轻松获取:TouchJSON 以下是简单的事例演示从douban movie请求JSON数据并转为字典对象后对控件赋 ...
- Excel 设置标题栏
1. 选中列表标题行, 可以设置字体居中显示,并放大字体以表示这是标题栏. 2. 选中列表第一数据行,即列表标题行下一行,选择View > Freeze Panes.
- liunx中安装包及其应用
1. dpkg -i <package> 安装包 dpkg -r <package> 删除包 dpkg -P <package> 移除包和配置文件 dpkg ...
- BZOJ4897: [Thu Summer Camp2016]成绩单【DP of DP】
Description 期末考试结束了,班主任L老师要将成绩单分发到每位同学手中.L老师共有n份成绩单,按照编号从1到n的顺序叠 放在桌子上,其中编号为i的成绩单分数为w_i.成绩单是按照批次发放的. ...
- 文件和文件夹不存在的时候,FileSystemWatcher 监听不到文件的改变?如果递归地监听就可以了
当你需要监视文件或文件夹的改变的时候,使用 FileSystemWatcher 便可以完成.不过,FileSystemWatcher 对文件夹的监视要求文件夹必须存在,否则会产生错误“无效路径”. 那 ...
- 获取的时候报cannot find package "golang.org /x/net/context",编译也报错误
gitclone 这个https://github.com/golang/net.git ,编译通过了. 创建了相应的golang.org/x/ 路径, 然后将克隆的目录 放回golang.org/ ...
- day39 python 学习 数据库学习 五个约束,数据库设计(一对一,一对多等等)
删除重复数据: 注意数据库不能又查又删 *******#删除作者为重复数据并保留ID最大的是数据 delete from ren where author in (select * from(sel ...
- 作为一名IT从业者,你在工作和学习中,遇到哪些问题
版权声明:襄阳雷哥的版权声明 https://blog.csdn.net/FansUnion/article/details/28448975 大家都是IT从业者,遇到的问题多少与类似. 假设能把这些 ...
- 【转】每天一个linux命令(11):nl命令
原文网址:http://www.cnblogs.com/peida/archive/2012/11/01/2749048.html nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件 ...