一:任务调度和资源调度的区别:

任务调度是指通过DAGScheduler,TaskScheduler,SchedulerBackend完成的job的调度

资源调度是指应用程序获取资源的调度,他是通过schedule方法完成的

二:资源调度解密

因为master负责资源管理和调度,所以资源调度的方法schedule位于master.scala这个了类中,当注册程序或者资源发生改变的都会导致schedule的调用,例如注册程序的时候(包括worker,driver和application的注册等,注意executor是向SparkDeploySchedulerBackend注册的)

case RegisterApplication(description, driver) => {
// TODO Prevent repeated registrations from some driver
if (state == RecoveryState.STANDBY) {
// ignore, don't send response
} else {
logInfo("Registering app " + description.name)
val app = createApplication(description, driver)
registerApplication(app)
logInfo("Registered app " + description.name + " with ID " + app.id)
persistenceEngine.addApplication(app)
driver.send(RegisteredApplication(app.id, self))
schedule()
}
**
* Schedule the currently available resources among waiting apps. This method will be called
* every time a new app joins or resource availability changes.
*/

每当新的应用程序加入或者可用资源发生改变(比如exccutor或者worker增加或者减少的时候)的时候,该方法都会发生响应

private def schedule(): Unit = {
if (state != RecoveryState.ALIVE) { return }//判断Master的状态是否为ALIVE,如果不是,则调度没有任何意义
// Drivers take strict precedence over executors
val shuffledWorkers = Random.shuffle(workers) // Randomization helps balance drivers //将workers随机化,有利于负载均衡
for (worker <- shuffledWorkers if worker.state == WorkerState.ALIVE) {//判断worker的状态,只有Alive级别的worker才能参与资源的分配工作
for (driver <- waitingDrivers) {//循环遍历等待中的driver,当然这里指的是cluster模式,如果是client模式的话,driver就自动启动了。
if (worker.memoryFree >= driver.desc.mem && worker.coresFree >= driver.desc.cores) { //当worker的free内存和cpu比driver所需要的多的时候,将driver放到workers中随机的一个worker,启动driver
launchDriver(worker, driver)
waitingDrivers -= driver//将启动的driver在等待队列中移除。
}
}
}
startExecutorsOnWorkers()
}

schedule的代码解析(简单的就放在上面的代码注释里了)

Random.shuffle(workers)  将worker在master缓存数据结构中的顺序打乱

def shuffle[T, CC[X] <: TraversableOnce[X]](xs: CC[T])(implicit bf: CanBuildFrom[CC[T], T, CC[T]]): CC[T] = {
val buf = new ArrayBuffer[T] ++= xs//构建一个临时的缓冲数组 def swap(i1: Int, i2: Int) {//交换数组中指定下表的两个元素
val tmp = buf(i1)
buf(i1) = buf(i2)
buf(i2) = tmp
} for (n <- buf.length to by -) {//生成随机数,并不停交换,打乱了数组中元素的顺序
val k = nextInt(n)
swap(n - , k)
} (bf(xs) ++= buf).result//返回随机化的新集合(这里就是workers的集合了)
}

2 waitingDrivers

private val waitingDrivers = new ArrayBuffer[DriverInfo]

可以看到这里waitingDrivers是一个数据元素为DriverInfo的数组,DriverInfo包含了driver的信息startTime(启动时间),id,desc(driver的描述信息),submitDate(提交日期)

private[deploy] class DriverInfo(
val startTime: Long,
val id: String,
val desc: DriverDescription,
val submitDate: Date)
extends Serializable { 其中描述信息包含了一下内容 private[deploy] case class DriverDescription(
jarUrl: String,//jar包地址
mem: Int,//内存信息
cores: Int,//CPU
supervise: Boolean//当spark-submit指定driver在cluster模式下运行的话如果设定了supervise,driver挂掉的时候回自动重启,
command: Command) {//一些环境信息 override def toString: String = s"DriverDescription (${command.mainClass})"
}

3 launchDriver spark只有先启动driver才能进行后面具体的调度

private def launchDriver(worker: WorkerInfo, driver: DriverInfo) {
logInfo("Launching driver " + driver.id + " on worker " + worker.id)
worker.addDriver(driver)//表明driver运行的worker
driver.worker = Some(worker)//driver和worker的相互引用
worker.endpoint.send(LaunchDriver(driver.id, driver.desc))//master通过远程rpc发指令给worker,让worker启动driver。
driver.state = DriverState.RUNNING//启动之后将driver的状态转为RUNNING
}

4 startExecutorsOnWorkers 先进先出的队列方式进行简单调度,spark默认启动Executor的方式是FIFO的方式,只有前一个app满足了资源分配的基础上,才会为下一个应用程序分配资源

/**
* Schedule and launch executors on workers
*/
private def startExecutorsOnWorkers(): Unit = {
// Right now this is a very simple FIFO scheduler. We keep trying to fit in the first app
// in the queue, then the second app, etc.
for (app <- waitingApps if app.coresLeft > ) {//为应用程序具体分配Executor之前会判断当前应用程序是否还需要cores,
如果不需要则不会为应用程序分配Executor
val coresPerExecutor: Option[Int] = app.desc.coresPerExecutor//应用程序所需要的cores
// Filter out workers that don't have enough resources to launch an executor //过滤掉不满足条件的worker,条件为:worker的状态必须是AlIVE的,worker的内存和cpu必须比每一个Executor所需要的大。 //过滤完之后,按照可用cores进行排序,并将大的放到前面,最优的最先使用。
val usableWorkers = workers.toArray.filter(_.state == WorkerState.ALIVE)
.filter(worker => worker.memoryFree >= app.desc.memoryPerExecutorMB &&
worker.coresFree >= coresPerExecutor.getOrElse())
.sortBy(_.coresFree).reverse //这里采用spreadOutApps的方式来让应用程序尽可能分散的运行在每一个Node上,这种方式往往能顺便带来更好的数据本地性,通常数据是分散的分布在各台机器上,这种方式通常也是默认的。这方法返回的是每一个分配给每一个worker的cores的数组。具体的在分配cores的时候回尽可能的满足当前所需的
val assignedCores = scheduleExecutorsOnWorkers(app, usableWorkers, spreadOutApps) // Now that we've decided how many cores to allocate on each worker, let's allocate them //下面进行真正的分配Executors,Master通过远程通信发指令给Worker来启动ExecutorBackend进程,向driver发送ExecutorAdded通信。
for (pos <- until usableWorkers.length if assignedCores(pos) > ) {
allocateWorkerResourceToExecutors(
app, assignedCores(pos), coresPerExecutor, usableWorkers(pos))
}
}
}

Spark资源调度的更多相关文章

  1. [Spark内核] 第31课:Spark资源调度分配内幕天机彻底解密:Driver在Cluster模式下的启动、两种不同的资源调度方式源码彻底解析、资源调度内幕总结

    本課主題 Master 资源调度的源码鉴赏 [引言部份:你希望读者看完这篇博客后有那些启发.学到什么样的知识点] 更新中...... 资源调度管理 任务调度与资源是通过 DAGScheduler.Ta ...

  2. 【Spark篇】---Spark资源调度和任务调度

    一.前述 Spark的资源调度是个很重要的模块,只要搞懂原理,才能具体明白Spark是怎么执行的,所以尤其重要. 自愿申请的话,本文分粗粒度和细粒度模式分别介绍. 二.具体 Spark资源调度流程图: ...

  3. 【Spark-core学习之六】 Spark资源调度和任务调度

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk1.8 scala-2.10.4(依赖jdk1.8) spark ...

  4. Spark 资源调度 与 任务调度

    Spark 资源调度与任务调度的流程(Standalone): 启动集群后, Worker 节点会向 Master 节点汇报资源情况, Master掌握了集群资源状况. 当 Spark 提交一个 Ap ...

  5. Spark 资源调度包 stage 类解析

    spark 资源调度包 Stage(阶段) 类解析 Stage 概念 Spark 任务会根据 RDD 之间的依赖关系, 形成一个DAG有向无环图, DAG会被提交给DAGScheduler, DAGS ...

  6. Spark资源调度和任务调度

    一.资源调度&任务调度 1.启动集群后,Worker节点会周期性的[心跳]向Master节点汇报资源情况,Master掌握集群资源情况. 2.当Spark提交一个Application后,根据 ...

  7. Spark资源调度分配内幕天机彻底解密:Driver在Cluster模式下的启动、两种不同的资源调度方式源码彻底解析、资源调度内幕总结

    本课主题 Master 资源调度的源码鉴赏 资源调度管理 任务调度与资源是通过 DAGScheduler.TaskScheduler.SchedulerBackend 等进行的作业调度 资源调度是指应 ...

  8. Spark 资源调度及任务调度

    1.  资源分配 通过SparkSubmit进行提交应用后,首先会创建Client将应用程序(字节码文件.class)包装成Driver,并将其注册到Master.Master收到Client的注册请 ...

  9. Spark资源调度及任务调度

    1.  资源分配 通过SparkSubmit进行提交应用后,首先会创建Client将应用程序(字节码文件.class)包装成Driver,并将其注册到Master.Master收到Client的注册请 ...

随机推荐

  1. 试一下Markdown

    Markdown 没想到博客园居然能够有markdown这样的写法了,以前觉得有自定义CSS已经非常不错了,现在居然加入Markdown,太值得称赞了.国内的博客系统,应该首屈一指了. 强调 你要走, ...

  2. [原]Jenkins(十四)---jenkins示例:admin管理所有项目,新建用户只能看部分项目

    /** * lihaibo * 文章内容都是根据自己工作情况实践得出. *如有错误,请指正 * 版权声明:本博客欢迎转发,但请保留原作者信息! http://www.cnblogs.com/horiz ...

  3. MySQL 之 表操作

    一 什么是表 表(TABLE) 是一种结构化的文件,可用来存储某种特定类型的数据.表中的一条记录有对应的标题,标题 称之为 表的字段. 二 创建表 1 2 3 4 5 CREATE TABLE 表名( ...

  4. python中的细节

    # 1 # li = ['a', 'b', 'c', 'd','e'] # print(li[10:]) #[] 不报错 # 2 # 这不是True或False,而是值 # 另外,优先级 not &g ...

  5. 洛谷 P1059明明的随机数 & P1068分数线划定 & P1781宇宙总统

    题目:https://www.luogu.org/problemnew/show/P1059 思路:STL中的set使用. //#include<bits/stdc++.h> #inclu ...

  6. STL 标准模板库

    <vector> 可变长的数组 Vector<int>v int是一个模板参数,这样传进来的都会是int V.push_back(a)将a传进v,且放在最后一个 V.clear ...

  7. 如何选择windows 10 系统中默认打开程序

    有时候我们会遇到打开某些文件需要通过open with 选择打开的应用程序,然后再点选always open with. 但是有时候这个方法不起作用,我们可以用如下方法: 1.从settings找到a ...

  8. .NET Core HttpClient调用腾讯云对象存储Web API的"ERROR_CGI_PARAM_NO_SUCH_OP"问题

    开门见山地说一下问题的原因:调用 web api 时请求头中多了双引号,请求体中少了双引号. 腾讯云提供的对象存储(COS)C# SDK 是基于 .NET Framework 用 WebRequest ...

  9. Navicat工具、pymysql模块 sql注入

    cls超 Navicat工具.pymysql模块 阅读目录 一 IDE工具介绍 二 pymysql模块 一 IDE工具介绍(Navicat) 生产环境还是推荐使用mysql命令行,但为了方便我们测试, ...

  10. ThinkPHP最简教程

    这里不讲原理,只讲操作. 这里不说MVC,只说目录(文件夹)结构. 假设Apache Http Server.PHP.MySql都已经安装完毕并已配置完毕,能够输出phpinfo(). 框架是什么? ...