spark中有多种资源调度方式。
1.应用间调度
运行中的集群里,每个spark应用都拥有独立的executor JVM用来运行任务和存储数据。如果多个用户需要共享这个集群,那么集群管理者会使用不同的方式来管理资源分配情况。 最简单的一种方式是将资源进行静态分区,通过这种方式,每个应用会得到它能使用的最大的资源量并且在它的整个运行过程中一直都会被持有。spark的standalone和YARN,粗粒度mesos模式都是使用的这种方式。具体的资源分配方式见下:
2.应用程序内调度
在一个指定的应用程序(一个SparkContext实例)里面,多个从不同线程提交的job可以并行运行。本节的job指的是某个spark的action(如:save,collect)和任何计算这些action的任务。spark的调度器是线程安全,所以它可以同时响应多个请求。 默认情况spark的调度器是按FIFO顺序执行job的,每个job会被分成多个步骤(如:map,reduce),第一个job会优先获得资源,接着第二个job,以此类推运行。如果队列中的处于head的job不需要使用整个集群的资源,后面的job会立即得到运行,当队列中处于head的job很大,那么后续的job就会明显的被延迟执行。 在spark0.8以后,spark提供了公平调度方式。通过使用公平调度方式,spark使用循环的方式为job指派任务,所以每个job会得到相近的资源。这意味着当一个长时间的job正在运行时,短时间的job也能立即得到资源被执行。 通过以下代码就可以使用公平调度器:
val conf = new SparkConf().setMaster(...).setAppName(...)
conf.set("spark.scheduler.mode", "FAIR")
val sc = new SparkContext(conf)
公平调度器池
公平调度器同时也支持将job归并入池中,这时可以对每个池进行不同的设置。在这种情况下就可以对那些重要的job所在的池设置高优先级使其能得到优先执行。 在没有任何的干预下,最新提交的job将会放入默认池中,但SparkContext通过设置spark.scheduler.pool属性后,那么在这个线程中提交的job(比如RDD.save,count,collect等)都会被放入该属性设置的池中:
// Assuming sc is your SparkContext variable
sc.setLocalProperty("spark.scheduler.pool", "pool1")
当需要清楚当前线程的池则简单将值设置为null即可。
池的默认行为
默认情况下,每个池得到的资源都是一样的(默认池中的job也会得到一样的资源),除默认池外其他池中的job还是按FIFO形式执行。
池的相关属性
conf.set("spark.scheduler.allocation.file", "/path/to/file")
xml文件内容如下:
<?xml version="1.0"?>
<allocations>
<pool name="production">
<schedulingMode>FAIR</schedulingMode>
<weight>1</weight>
<minShare>2</minShare>
</pool>
<pool name="test">
<schedulingMode>FIFO</schedulingMode>
<weight>2</weight>
<minShare>3</minShare>
</pool>
</allocations>
注意:在xml文件中未配置的pool将会使用spark的默认调度方式和属性(schedulerMode=FIFO,weight=1,minShare=0)