Spark Driver和Executor资源调度学习

[size=medium][color=red][b]一、引子[/b][/color][/size]
在Worker Actor中,每次LaunchExecutor会创建一个CoarseGrainedExecutorBackend进程,Executor和CoarseGrainedExecutorBackend是1对1的关系。也就是说集群里启动多少Executor实例就有多少CoarseGrainedExecutorBackend进程。
那么到底是如何分配Executor的呢?怎么控制调节Executor的个数呢?

[size=medium][color=red][b]二、Driver和Executor资源调度[/b][/color][/size]
下面主要介绍一下Spark Executor分配策略:
我们仅看,当Application提交注册到Master后,Master会返回RegisteredApplication,之后便会调用schedule()这个方法,来分配Driver的资源,和启动Executor的资源。
schedule()方法是来调度当前可用资源的调度方法,它管理还在排队等待的Apps资源的分配,这个方法是每次在集群资源发生变动的时候都会调用,根据当前集群最新的资源来进行Apps的资源分配。

[size=medium][b]Driver资源调度:[/b][/size]
随机的将Driver分配到空闲的Worker上去

// First schedule drivers, they take strict precedence over applications  
val shuffledWorkers = Random.shuffle(workers) // 把当前workers这个HashSet的顺序随机打乱
for (worker <- shuffledWorkers if worker.state == WorkerState.ALIVE) { //遍历活着的workers
for (driver <- waitingDrivers) { //在等待队列中的Driver们会进行资源分配
if (worker.memoryFree >= driver.desc.mem && worker.coresFree >= driver.desc.cores) { //当前的worker内存和cpu均大于当前driver请求的mem和cpu,则启动
launchDriver(worker, driver) //启动Driver 内部实现是发送启动Driver命令给指定Worker,Worker来启动Driver。
waitingDrivers -= driver //把启动过的Driver从队列移除
}
}
}


[size=medium][b]Executor资源调度:[/b][/size]
Spark默认提供了一种在各个节点进行round-robin的调度,用户可以自己设置这个flag
val spreadOutApps = conf.getBoolean("spark.deploy.spreadOut", true)  

在介绍之前我们先介绍一个概念,

[b]可用的Worker:[/b]什么是可用,可用就是[color=red][b]资源空闲足够且满足一定的规则[/b][/color]来启动当前App的Executor。
Spark定义了一个canUse方法:这个方法接受一个ApplicationInfo的描述信息和当前Worker的描述信息。
1、当前worker的空闲内存比该app在每个slave要占用的内存 (executor.memory默认512M)大
[color=blue][b]2、当前app从未在此worker启动过App[/b][/color]

总结: 从这点看出,要满足:该Worker的当前可用最小内存要比配置的executor内存大,并且对于同一个App只能在一个Worker里启动一个Exeutor,如果要启动第二个Executor,那么请到其它Worker里。这样的才算是对App可用的Worker。


/**
* Can an app use the given worker? True if the worker has enough memory and we haven't already
* launched an executor for the app on it (right now the standalone backend doesn't like having
* two executors on the same worker).
*/
def canUse(app: ApplicationInfo, worker: WorkerInfo): Boolean = {
worker.memoryFree >= app.desc.memoryPerSlave && !worker.hasExecutor(app)

}

[size=medium][color=red][b]SpreadOut分配策略:[/b][/color][/size]
SpreadOut分配策略是一种以round-robin方式遍历集群所有可用Worker,分配Worker资源,来启动创建Executor的策略,[b]好处是尽可能的将cores分配到各个节点[/b],最大化负载均衡和高并行。

[size=medium][color=red][b]非SpreadOut分配策略:[/b][/color][/size]
非SpreadOut策略,该策略:[b]会尽可能的根据每个Worker的剩余资源来启动Executor[/b],这样启动的Executor可能只在集群的一小部分机器的Worker上。这样做对node较少的集群还可以,集群规模大了,Executor的并行度和机器负载均衡就不能够保证了。

[b]程序运行的时候,Driver向Master申请资源;[/b]
Master让Worker给程序分配具体的Executor。
下面就是Driver具体的调用过程:
[color=red][b]通过DAGScheduler划分阶段,形成一系列的TaskSet,然后传给TaskScheduler,把具体的Task交给Worker节点上的Executor的线程池处理。线程池中的线程工作,通过BlockManager来读写数据。 [/b][/color]
这就是4大组件:Worker、Master、Executor、Driver之间的协同工作。

转自:[url]http://blog.csdn.net/oopsoom/article/details/38763985[/url]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值