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的文档,我想应该是可以开始你的数据分析之路的.这一篇文章,着重进行一些简单的思路上的引导和分析.如果你分析招聘数据时,卡在了某 ...
随机推荐
- Python 文件复制_bytes
f1 = open("c:/huyifei.jpg", mode="rb") f2 = open("d:/huerfei.jpg", mod ...
- ubuntu18.04 server配置静态ip (转载)
原文地址: https://blog.csdn.net/mossan/article/details/80381679 最新发布的ubuntu18.04 server,启用了新的网络工具netplan ...
- Linux C single linked for any data type
/************************************************************************** * Linux C single linked ...
- OK335xS I2C device registe hacking
/*************************************************************************** * OK335xS I2C device re ...
- JQuery 基本知识,选择器,事件,DOM操作
一.基本知识 Jquery是什么? 它就是一套JS方法包,jQuery是一个快速,小巧,功能丰富的JavaScript库.它使得HTML文档遍历和操作,事件处理,动画和Ajax更容易使用易于使用的AP ...
- hdu1238 Substrings 扩展KMP
You are given a number of case-sensitive strings of alphabetic characters, find the largest string X ...
- 使用systemd严格保证启动顺序
需求: 服务B要在服务A之后启动,且由于存在强内在依赖关系,B必须在A完成初始化之后才能被启动. 解决方法: 首先使用systemd,service脚本需要配置服务B要after服务A. 其次,A服务 ...
- 八、面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)
面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...
- oracle常用数据类型说明
类型 含义 存储描述 备注 CHAR 固定长度字符串 最大长度2000bytes VARCHAR2 可变长度的字符串, 最大长度4000bytes 可做索引的最大长度749 NCHAR 根据字符集而定 ...
- 求交错序列前N项和(15 分)
7-2 求交错序列前N项和(15 分) 本题要求编写程序,计算交错序列 1-2/3+3/5-4/7+5/9-6/11+... 的前N项之和. 输入格式: 输入在一行中给出一个正整数N. 输出格式: 在 ...