spark1.3.x与spark2.x启动executor不同的cpu core分配方式
***这里的executor在worker上分配策略以spreadOut 为例***
1.3版本关键点:
for (app <- waitingApps if app.coresLeft > 0) { //对还未被完全分配资源的apps处理
val usableWorkers = workers.toArray.filter(_.state == WorkerState.ALIVE)
.filter(canUse(app, _)).sortBy(_.coresFree).reverse //根据core Free对可用Worker进行降序排序。
val numUsable = usableWorkers.length //可用worker的个数 eg:可用5个worker
val assigned = new Array[Int](numUsable) //候选Worker,每个Worker一个下标,是一个数组,初始化默认都是0
var toAssign = math.min(app.coresLeft, usableWorkers.map(_.coresFree).sum)//还要分配的cores = 集群中可用Worker的可用cores总和(10), 当前未分配core(5)中找最小的
var pos = 0
while (toAssign > 0) {
if (usableWorkers(pos).coresFree - assigned(pos) > 0) { //以round robin方式在所有可用Worker里判断当前worker空闲cpu是否大于当前数组已经分配core值
toAssign -= 1
assigned(pos) += 1 //当前下标pos的Worker分配1个core +1
}
pos = (pos + 1) % numUsable //round-robin轮询寻找有资源的Worker
}
// Now that we've decided how many cores to give on each node, let's actually give them
for (pos <- 0 until numUsable) {
if (assigned(pos) > 0) { //如果assigned数组中的值>0,将启动一个executor在,指定下标的机器上。
val exec = app.addExecutor(usableWorkers(pos), assigned(pos)) //更新app里的Executor信息
launchExecutor(usableWorkers(pos), exec) //通知可用Worker去启动Executor
app.state = ApplicationState.RUNNING
}
}
}
以上红色代码清晰的展示了在平均分配的场景下,每次会给worker分配1个core,所以说在spark-submit中如果设置了 --executor-cores属性未必起作用;
但在2.x版本的spark中却做了这方面的矫正,它确实会去读取--executor-cores属性中的值,如果该值未设置则依然按照1.3.x的方式执行,代码如下:
private def scheduleExecutorsOnWorkers(
app: ApplicationInfo,
usableWorkers: Array[WorkerInfo],
spreadOutApps: Boolean): Array[Int] = {
val coresPerExecutor = app.desc.coresPerExecutor
val minCoresPerExecutor = coresPerExecutor.getOrElse(1)
val oneExecutorPerWorker = coresPerExecutor.isEmpty
val memoryPerExecutor = app.desc.memoryPerExecutorMB
val numUsable = usableWorkers.length
val assignedCores = new Array[Int](numUsable) // Number of cores to give to each worker
val assignedExecutors = new Array[Int](numUsable) // Number of new executors on each worker
var coresToAssign = math.min(app.coresLeft, usableWorkers.map(_.coresFree).sum) /** Return whether the specified worker can launch an executor for this app. */
def canLaunchExecutor(pos: Int): Boolean = {
val keepScheduling = coresToAssign >= minCoresPerExecutor
val enoughCores = usableWorkers(pos).coresFree - assignedCores(pos) >= minCoresPerExecutor // If we allow multiple executors per worker, then we can always launch new executors.
// Otherwise, if there is already an executor on this worker, just give it more cores.
val launchingNewExecutor = !oneExecutorPerWorker || assignedExecutors(pos) == 0
if (launchingNewExecutor) {
val assignedMemory = assignedExecutors(pos) * memoryPerExecutor
val enoughMemory = usableWorkers(pos).memoryFree - assignedMemory >= memoryPerExecutor
val underLimit = assignedExecutors.sum + app.executors.size < app.executorLimit
keepScheduling && enoughCores && enoughMemory && underLimit
} else {
// We're adding cores to an existing executor, so no need
// to check memory and executor limits
keepScheduling && enoughCores
}
} // Keep launching executors until no more workers can accommodate any
// more executors, or if we have reached this application's limits
var freeWorkers = (0 until numUsable).filter(canLaunchExecutor)
while (freeWorkers.nonEmpty) {
freeWorkers.foreach { pos =>
var keepScheduling = true
while (keepScheduling && canLaunchExecutor(pos)) {
coresToAssign -= minCoresPerExecutor
assignedCores(pos) += minCoresPerExecutor // If we are launching one executor per worker, then every iteration assigns 1 core
// to the executor. Otherwise, every iteration assigns cores to a new executor.
if (oneExecutorPerWorker) {
assignedExecutors(pos) = 1
} else {
assignedExecutors(pos) += 1
} // Spreading out an application means spreading out its executors across as
// many workers as possible. If we are not spreading out, then we should keep
// scheduling executors on this worker until we use all of its resources.
// Otherwise, just move on to the next worker.
if (spreadOutApps) {
keepScheduling = false
}
}
}
freeWorkers = freeWorkers.filter(canLaunchExecutor)
}
assignedCores
}
spark1.3.x与spark2.x启动executor不同的cpu core分配方式的更多相关文章
- worker启动executor源码分析-executor.clj
在"supervisor启动worker源码分析-worker.clj"一文中,我们详细讲解了worker是如何初始化的.主要通过调用mk-worker函数实现的.在启动worke ...
- [Spark内核] 第32课:Spark Worker原理和源码剖析解密:Worker工作流程图、Worker启动Driver源码解密、Worker启动Executor源码解密等
本課主題 Spark Worker 原理 Worker 启动 Driver 源码鉴赏 Worker 启动 Executor 源码鉴赏 Worker 与 Master 的交互关系 [引言部份:你希望读者 ...
- Spark Worker原理和源码剖析解密:Worker工作流程图、Worker启动Driver源码解密、Worker启动Executor源码解密等
本课主题 Spark Worker 原理 Worker 启动 Driver 源码鉴赏 Worker 启动 Executor 源码鉴赏 Worker 与 Master 的交互关系 Spark Worke ...
- Android Activity启动黑/白屏原因与解决方式
Android Activity启动黑/白屏原因与解决方式 我们新建一个HelloWorld项目,运行在手机上时,Activity打开之前会有一个动画,而这个动画里是全白或者全黑的(取决于你的主题是亮 ...
- docker 启动报错:Docker.Core.Backend.BackendException: Error response from daemon: open \\.\pipe\docker_e
win10 docker启动后报错: Docker.Core.Backend.BackendException:Error response from daemon: open \\.\pipe\do ...
- 04_线程的创建和启动_使用Callable和Future的方式
[简述] 从java5开始,java提供了Callable接口,这个接口可以是Runnable接口的增强版, Callable接口提供了一个call()方法作为线程执行体,call()方法比run() ...
- web容器启动后自动执行程序的几种方式比较
1. 背景 1.1. 背景介绍 在web项目中我们有时会遇到这种需求,在web项目启动后需要开启线程去完成一些重要的工作,例如:往数据库中初始化一些数据,开启线程,初始化消息队 ...
- pythoncharm 中解决启动server时出现 “django.core.exceptions.ImproperlyConfigured: Requested setting DEBUG, but settings are not configured”的错误
背景介绍 最近,尝试着用pythoncharm 这个All-star IDE来搞一搞Django,于是乎,下载专业版,PJ等等一系列操作之后,终于得偿所愿.可以开工了. 错误 在园子里找了一篇初学者的 ...
- Oracle数据库启动出现ORA-27101错误之ORA-19815处理方式及数据备份
ORA-27101: sharedmemory realm does not exist之ORA-19815处理 重启数据库(数据库:muphy),登陆是越到错误: ORA-27101: shared ...
随机推荐
- C语言malloc函数为一维,二维,三维数组分配空间
c语言允许建立内存动态分配区域,以存放一些临时用的数据,这些数据不必在程序的声明部分定义,也不必等到函数结束时才释放,而是需要时随时开辟,不需要时随时释放,这些数据存储在堆区.可以根据需要,向系统申请 ...
- Lua的线程和状态
[那不是真的多线程] Lua不支持真正的多线程,这句话我在<Lua中的协同程序>这篇文章中就已经说了.根据我的编程经验,在开发过程中,如果可以避免使用线程,那就坚决不用线程,如果实在没有更 ...
- GIt -- Window下配置 git
全局配置 git config --global user.name "账户名" git config --global use r.email '账户邮箱' 生成ssh,命令 ...
- JsRender练习总结
1.假设的数据,基础部分. <div id="list1"></div> <script type="text/tmp" id=& ...
- javascript中Math函数的属性与方法
math函数的属性 Math.PI:返回圆周率. math函数的方法 绝对值: Math.abs(); 对数进行上舍入: Math.ceil(); 对数进行下舍入: Math.floor(); Mat ...
- 【python】多进程共享变量Manager
Manager的复杂结构赋值问题 Manager的字典类型: 如果value是简单类型,比如int,可以直接赋值给共享变量,并可以后续直接修改 如果value是复杂类型 ,比如list,dict,则必 ...
- cc.Component 的使用
1.组件入口函数,常有的:onLoad,start,update //组件在加载的时候运行,并且场景的初始化工作已经完成 onLoad() { }, //组件在第一次update调用之前调用 star ...
- sqlserver(查看被锁进程)
-- ###### 查看被锁进程 ###### select 标志, 进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid, 数据库名=db_name(dbid), ...
- thinkphp微信浏览器内拉起微信支付
vendor/wxpay/pay.php <?php /* +-----------------------------------+ | 微信支付类 | +------------------ ...
- elasticsearch单机部署多个节点
cp -r elasticsearch-2.4.4 elasticsearch-2.4.4-2 mv elasticsearch-2.4.4 elasticsearch-2.4.4-1 总共cp了三个 ...