4.2.1 Spark应用程序之间的调度
通过前面的介绍,读者了解到每个应用拥有对应的SparkContext.SparkContext维持整个应用的上下文信息,提供一些核心方法,如runJob可以提交Job。然后,通过主节点的分配获得独立的一组Executor JVM进程执行任务。Executor空间内的不同应用之间是不共享的,一个Executor在一个时间段内只能分配给一个应用使用。如果多用户需要共享集群资源,依据集群管理者的配置,用户可以通过不同的配置选项来分配管理资源。
对集群管理者来说简单的配置方式就是静态配置资源分配规则。例如,在不同的运行模式下,用户可以通过配置文件中进行集群调度的配置。配置每个应用可以使用的最大资源总量、调度的优先级等。
1.调度配置
下面根据不同集群的运行模式配置调度[1]。
(1)Standalone
默认情况下,用户向以Standalone模式运行的Spark集群提交的应用使用FIFO(先进先出)的顺序进行调度。每个应用会独占所有可用节点的资源。用户可以通过配置参数spark.cores.max决定一个应用可以在整个集群申请的CPU core数。注意,这个参数不是控制单节点可用多少核。如果用户没有配置这个参数,则在Standalone模式下,默认每个应用可以分配由参数spark.deploy.defaultCores决定的可用核数。
(2)Mesos
如果用户在Mesos上使用Spark,并且想要静态地配置资源的分配策略,则可以通过配置参数spark.mesos.coarse为true,将Mesos配置为粗粒度调度模式。然后配置参数spark.cores.max来限制应用可以使用的CPU core的最大限额。同时用户应该对参数spark.executor.memory进行配置,进而限制每个Executor的内存使用量。Mesos中还可以配置动态共享CPU core的执行模式,用户只需要使用mesos://URL而不配置spark.mesos.coarse参数为true,就能以这种方式执行,使Mesos运行在细粒度调度模型下。在这种模式下,每个Spark应用程序还是会拥有独立和固定的内存分配,但是当应用占用的一些机器上不再运行任务,机器处于空闲状态时,其他机器可以使用这些机器上空闲的CPU core来执行任务,相当于复用空闲的CPU提升了资源利用率。这种模式在集群上再运行大量不活跃的应用情景下十分有用,如大量不同用户发起请求的场景。
(3)YARN
当Spark运行在YARN平台上时,用户可以在YARN的客户端通过配置—num-executors选项控制为这个应用分配多少个Executor,然后通过配置—executor-memory及—executor-cores来控制应用被分到的每个Executor的内存大小和Executor所占用的CPU核数。这样便可以限制用户提交的应用不会过多的占用资源,让不同用户能够共享整个集群资源,提升YARN吞吐量。
注意:以上3种运行模式都不提供跨应用的共享内存。如果用户想共享内存数据,Spark官网推荐用户开发一个单机服务,这个服务可以接收多个对同一个RDD的查询请求,并返回结果,类似的Shark JDBC Server就是这样工作的,Spark SQL在新版本中也会提供这样的功能。目前版本,Spark SQL暂时使用的Shark Server2 Github地址为https://github.com/amplab/shark/tree/sparkSql。
Shark的Github地址为:https://github.com/amplab/shark。
2.FIFO的调度代码
最后,读者可以参考下面源码,了解在Standalone模式中,集群是如何完成应用FIFO的调度的。Spark的应用接收提交和调度的代码在Master.scala文件中,在schedule()方法中实现调度。
- private def schedule() {
- ……
- for (worker <- shuffledWorkers if worker.state == WorkerState.ALIVE) {
- for (driver <- List(waitingDrivers: _*)) {
- if (worker.memoryFree >= driver.desc.mem && worker.coresFree >= driver.desc.cores) {
- launchDriver(worker, driver)
- waitingDrivers -= driver
- }
- }
- }
从源码中可以看到,Master先统计可用资源,然后在waitingDrivers的队列中通过FIFO方式为App分配资源和指定Worker启动Driver执行应用。
[1] 参见:http://spark.apache.org/docs/latest/job-scheduling.html#scheduling-across-applications。