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的更多相关文章

  1. 使用Spark分析拉勾网招聘信息(一):准备工作

    本系列专属github地址:https://github.com/ios122/spark_lagou 前言 我觉得如果动笔,就应该努力地把要说的东西表达清楚.今后一段时间,尝试下系列博客文章.简单说 ...

  2. [大数据从入门到放弃系列教程]第一个spark分析程序

    [大数据从入门到放弃系列教程]第一个spark分析程序 原文链接:http://www.cnblogs.com/blog5277/p/8580007.html 原文作者:博客园--曲高终和寡 **** ...

  3. Spark Scheduler模块源码分析之TaskScheduler和SchedulerBackend

    本文是Scheduler模块源码分析的第二篇,第一篇Spark Scheduler模块源码分析之DAGScheduler主要分析了DAGScheduler.本文接下来结合Spark-1.6.0的源码继 ...

  4. Spark Core Runtime分析: DAGScheduler, TaskScheduler, SchedulerBackend

    Spark Runtime里的主要层次分析,梳理Runtime组件和运行流程, DAGScheduler Job=多个stage,Stage=多个同种task, Task分为ShuffleMapTas ...

  5. spark 源码分析之四 -- TaskScheduler的创建和启动过程

    在 spark 源码分析之二 -- SparkContext 的初始化过程 中,第 14 步 和 16 步分别描述了 TaskScheduler的 初始化 和 启动过程. 话分两头,先说 TaskSc ...

  6. Spark分析之Job Scheduling Process

    经过前面文章的SparkContext.DAGScheduler.TaskScheduler分析,再从总体上了解Spark Job的调度流程 1.SparkContext将job的RDD DAG图提交 ...

  7. Spark分析之SparkContext启动过程分析

    SparkContext作为整个Spark的入口,不管是spark.sparkstreaming.spark sql都需要首先创建一个SparkContext对象,然后基于这个SparkContext ...

  8. Spark分析之DAGScheduler

    DAGScheduler概述:是一个面向Stage层面的调度器: 主要入参有: dagScheduler.runJob(rdd, cleanedFunc, partitions, callSite, ...

  9. 使用Spark分析拉勾网招聘信息(四): 几个常用的脚本与图片分析结果

    概述 前一篇文章,已经介绍了BMR的基础用法,再结合Spark和Scala的文档,我想应该是可以开始你的数据分析之路的.这一篇文章,着重进行一些简单的思路上的引导和分析.如果你分析招聘数据时,卡在了某 ...

随机推荐

  1. Python 文件复制_bytes

    f1 = open("c:/huyifei.jpg", mode="rb") f2 = open("d:/huerfei.jpg", mod ...

  2. ubuntu18.04 server配置静态ip (转载)

    原文地址: https://blog.csdn.net/mossan/article/details/80381679 最新发布的ubuntu18.04 server,启用了新的网络工具netplan ...

  3. Linux C single linked for any data type

    /************************************************************************** * Linux C single linked ...

  4. OK335xS I2C device registe hacking

    /*************************************************************************** * OK335xS I2C device re ...

  5. JQuery 基本知识,选择器,事件,DOM操作

    一.基本知识 Jquery是什么? 它就是一套JS方法包,jQuery是一个快速,小巧,功能丰富的JavaScript库.它使得HTML文档遍历和操作,事件处理,动画和Ajax更容易使用易于使用的AP ...

  6. hdu1238 Substrings 扩展KMP

    You are given a number of case-sensitive strings of alphabetic characters, find the largest string X ...

  7. 使用systemd严格保证启动顺序

    需求: 服务B要在服务A之后启动,且由于存在强内在依赖关系,B必须在A完成初始化之后才能被启动. 解决方法: 首先使用systemd,service脚本需要配置服务B要after服务A. 其次,A服务 ...

  8. 八、面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)

    面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...

  9. oracle常用数据类型说明

    类型 含义 存储描述 备注 CHAR 固定长度字符串 最大长度2000bytes VARCHAR2 可变长度的字符串, 最大长度4000bytes 可做索引的最大长度749 NCHAR 根据字符集而定 ...

  10. 求交错序列前N项和(15 分)

    7-2 求交错序列前N项和(15 分) 本题要求编写程序,计算交错序列 1-2/3+3/5-4/7+5/9-6/11+... 的前N项之和. 输入格式: 输入在一行中给出一个正整数N. 输出格式: 在 ...