Job Scheduling

Overview

Spark有几种用于在计算之间调度资源的工具。 首先,回想一下,如集群模式概述中所述,每个Spark应用程序(SparkContext的实例)都运行一组独立的执行程序进程。 Spark运行的集群管理器提供跨应用程序进行调度的工具。 其次,在每个Spark应用程序中,如果多个“作业”(Spark动作)由不同的线程提交,则它们可以同时运行。 如果您的应用程序通过网络提供请求,则这很常见。 Spark包含一个公平的调度程序来调度每个SparkContext中的资源。

Scheduling Across Applications(跨应用程序进行调度)

在集群上运行时,每个Spark应用程序都会获得一组独立的执行程序JVM,它们只运行任务并为该应用程序存储数据。 如果多个用户需要共享您的群集,则可以使用不同的选项来管理分配,具体取决于群集管理器。

所有集群管理器上都可以使用的最简单选项是静态分区资源。 通过这种方法,每个应用程序都可以使用最大量的资源,并在整个持续时间内保留它们。 这是Spark独立和YARN模式中使用的方法,以及粗粒度Mesos模式。 可以根据群集类型配置资源分配如下:

  • Standalone mode:默认情况下,提交到独立模式群集的应用程序将以FIFO(先进先出)顺序运行,每个应用程序将尝试使用所有可用节点。 您可以通过在其中设置spark.cores.max配置属性来限制应用程序使用的节点数,或者更改未通过spark.deploy.defaultCores设置此设置的应用程序的默认值。 最后,除了控制核心,每个应用程序的spark.executor.memory设置控制其内存使用。
  • Mesos: 要在Mesos上使用静态分区,请将spark.mesos.coarse配置属性设置为true,并可选择设置spark.cores.max以限制每个应用程序的资源共享,就像在独立模式下一样。 您还应该设置spark.executor.memory来控制执行程序内存。
  • YARN:Spark YARN客户端的–num-executors选项控制它将在集群上分配的执行程序数(spark.executor.instances作为配置属性),而–executor-memory(spark.executor.memory配置属性) 和–executor-cores(spark.executor.cores配置属性)控制每个执行程序的资源。 有关更多信息,请参阅YARN Spark属性。

Mesos上的第二个选项是动态共享CPU内核。 在此模式下,每个Spark应用程序仍然具有固定且独立的内存分配(由spark.executor.memory设置),但是当应用程序未在计算机上运行任务时,其他应用程序可能会在这些核心上运行任务。 当您期望大量不过度活跃的应用程序(例如来自不同用户的shell会话)时,此模式非常有用。 但是,它存在延迟可预测性较低的风险,因为应用程序可能需要一段时间才能在一个节点上获取内核。 要使用此模式,只需使用mesos:// URL并将spark.mesos.coarse设置为false。

请注意,目前没有一种模式可以跨应用程序提供内存共享。 如果您希望以这种方式共享数据,我们建议运行单个服务器应用程序,通过查询相同的RDD来提供多个请求。

Dynamic Resource Allocation(动态资源分配)

Spark提供了一种机制,可根据工作负载动态调整应用程序占用的资源。 这意味着如果不再使用它们,您的应用程序可能会将资源返回给群集,并在有需求时再次请求它们。 如果多个应用程序共享Spark群集中的资源,则此功能特别有用。

默认情况下禁用此功能,并且可在所有粗粒度集群管理器上使用此功能,即独立模式,YARN模式和Mesos粗粒度模式。

Configuration and Setup

使用此功能有两个要求。首先,您的应用程序必须将spark.dynamicAllocation.enabled设置为true。其次,必须在同一集群中的每个工作节点上设置外部shuffle服务,并在应用程序中将spark.shuffle.service.enabled设置为true。外部shuffle服务的目的是允许删除执行程序而不删除由它们写入的shuffle文件(更详细描述如下)。设置此服务的方式因集群管理器而异:

在独立模式下,只需将spark.shuffle.service.enabled设置为true即可启动工作程序。

在Mesos粗粒度模式下,在spark.shuffle.service.enabled设置为true的所有从属节点上运行$ SPARK_HOME / sbin / start-mesos-shuffle-service.sh。例如,你可以通过Marathon这样做。

在YARN模式下,请按照此处的说明操作。

所有其他相关配置都是可选的,位于spark.dynamicAllocation。和spark.shuffle.service。命名空间下。有关更多详细信息,请参阅配置页面。

Resource Allocation Policy(资源分配政策)

在较高的层面上,Spark应该在不再使用执行程序时放弃执行程序,并在需要时获取执行程序。 由于没有确定的方法可以预测即将被删除的执行程序是否会在不久的将来运行任务,或者即将添加的新执行程序是否实际上是空闲的,我们需要一组启发式来确定 何时删除并请求执行者。

Request Policy

启用动态分配的Spark应用程序在等待计划等待挂起的任务时请求其他执行程序。这种情况必然意味着现有的执行者集合不足以同时使已提交但尚未完成的所有任务饱和。

Spark会轮次请求执行程序。当spark.dynamicAllocation.schedulerBacklogTimeout秒有挂起的任务时会触发实际请求,然后如果待处理任务队列仍然存在,则每次spark.dynamicAllocation.sustainedSchedulerBacklogTimeout秒再次触发。此外,每轮请求的执行者数量与上一轮相比呈指数增长。例如,一个应用程序将在第一轮中添加1个执行程序,然后在后续轮次中添加执行程序中的2,4,8等。

指数增长政策的动机是双重的。首先,应用程序应该在开始时谨慎地请求执行程序,以防只有少数额外的执行程序就足够了。这与TCP慢启动的理由相呼应。其次,应用程序应该能够及时提高其资源使用率,以防万一实际需要许多执行程序。

Remove Policy

删除执行程序的策略要简单得多。 Spark应用程序在空闲时间超过spark.dynamicAllocation.executorIdleTimeout秒时会删除执行程序。 请注意,在大多数情况下,此条件与请求条件互斥,因为如果仍有待安排的待处理任务,则执行程序不应处于空闲状态。

Graceful Decommission of Executors(执行者的优雅退役)

在动态分配之前,Spark执行程序会在失败时或关联的应用程序也退出时退出。在这两种情况下,不再需要与执行程序关联的所有状态,并且可以安全地丢弃。但是,通过动态分配,当显式删除执行程序时,应用程序仍在运行。如果应用程序尝试访问存储在执行程序中或由执行程序写入的状态,则必须执行重新计算状态。因此,Spark需要一种机制来通过在删除执行程序之前保留其状态来优雅地停用执行程序。

这一要求对于洗牌尤其重要。在shuffle期间,Spark执行程序首先将其自己的映射输出本地写入磁盘,然后在其他执行程序尝试获取这些文件时充当这些文件的服务器。如果straggler是比同行运行更长时间的任务,动态分配可能会在shuffle完成之前删除执行程序,在这种情况下,必须重新计算由该执行程序写入的shuffle文件。

保留shuffle文件的解决方案是使用外部shuffle服务,也在Spark 1.2中引入。此服务指的是一个长期运行的进程,它独立于Spark应用程序及其执行程序在集群的每个节点上运行。如果启用该服务,Spark执行程序将从服务而不是相互之间获取随机文件。这意味着遗嘱执行人所写的任何洗牌状态可能会继续在遗嘱执行人的有效期内提供。

除了编写shuffle文件外,执行程序还会将数据缓存在磁盘或内存中。但是,删除执行程序后,将无法再访问所有缓存的数据。为了缓解这种情况,默认情况下,永远不会删除包含缓存数据的执行程序。您可以使用spark.dynamicAllocation.cachedExecutorIdleTimeout配置此行为。在将来的版本中,缓存的数据可以通过堆外存储来保存,这类存储的精神与通过外部shuffle服务保存shuffle文件的方式类似。

Scheduling Within an Application

在给定的Spark应用程序(SparkContext实例)中,如果从单独的线程提交多个并行作业,则它们可以同时运行。对于“作业”,在本节中,我们指的是Spark操作(例如,保存,收集)以及需要运行以评估该操作的任何任务。 Spark的调度程序是完全线程安全的,并支持此用例,以支持提供多个请求的应用程序(例如,查询多个用户)。

默认情况下,Spark的调度程序以FIFO方式运行作业。每个工作分为“阶段”(例如地图和减少阶段),第一个工作优先于所有可用资源,而其阶段有任务要启动,然后第二个工作获得优先权等。如果工作在头部队列不需要使用整个集群,以后的作业可以立即开始运行,但如果队列头部的作业很大,则后续作业可能会显着延迟。

从Spark 0.8开始,还可以在作业之间配置公平共享。在公平共享下,Spark以“循环”方式在作业之间分配任务,以便所有作业获得大致相等的群集资源份额。这意味着在长时间工作运行时提交的短工作可以立即开始接收资源,并且仍然可以获得良好的响应时间,而无需等待长时间工作完成。此模式最适合多用户设置。

要启用公平调度程序,只需在配置SparkContext时将spark.scheduler.mode属性设置为FAIR:

val conf = new SparkConf().setMaster(...).setAppName(...)
conf.set("spark.scheduler.mode", "FAIR")
val sc = new SparkContext(conf)

Fair Scheduler Pools

公平调度程序还支持将作业分组到池中,并为每个池设置不同的调度选项(例如权重)。 例如,这可以用于为更重要的作业创建“高优先级”池,或者将每个用户的作业组合在一起,并为用户提供相同的份额,而不管他们拥有多少并发作业,而不是给予作业相等的份额。 此方法以Hadoop Fair Scheduler为模型。

在没有任何干预的情况下,新提交的作业将进入默认池,但可以通过将spark.scheduler.pool“local property”添加到提交它们的线程中的SparkContext来设置作业池。 这样做如下:

// Assuming sc is your SparkContext variable
sc.setLocalProperty("spark.scheduler.pool", "pool1")

设置此本地属性后,在此线程中提交的所有作业(通过此线程中的调用到RDD.save,count,collect等)将使用此池名称。 该设置是每个线程,以便让线程代表同一个用户运行多个作业变得容易。 如果您想清除与线程关联的池,只需调用:

sc.setLocalProperty("spark.scheduler.pool", null)

Default Behavior of Pools

默认情况下,每个池获得的集群份额相等(默认池中的每个作业的份额也相等),但在每个池中,作业按FIFO顺序运行。 例如,如果您为每个用户创建一个池,这意味着每个用户将获得相同的群集份额,并且每个用户的查询将按顺序运行,而不是以后的查询从该用户的早期查询中获取资源。

Configuring Pool Properties

还可以通过配置文件修改特定池的属性。每个池支持三个属性

  1. schedulingMode:这可以是FIFO或FAIR,用于控制池中的作业是否相互排队(默认)或公平地共享池的资源。
  2. weight:它控制池相对于其他池的共享。默认情况下,所有池的权重均为1.例如,如果为特定池提供权重2,则其资源将比其他活动池多2倍。设置高权重(例如1000)也可以实现池之间的优先级 - 实质上,只要有活动作业,weight-1000池就会始终首先启动任务。
  3. minShare:除了总体权重之外,每个池都可以获得管理员希望拥有的最小份额(作为许多CPU核心)。公平调度程序始终尝试满足所有活动池的最小份额,然后根据权重重新分配额外资源。因此,minShare属性可以是另一种确保池可以始终快速获得一定数量资源(例如10个核心)的方法,而不会为集群的其余部分提供高优先级。默认情况下,每个池的minShare为0。

可以通过创建XML文件来设置池属性,类似于conf / fairscheduler.xml.template,并在类路径中放置名为fairscheduler.xml的文件,或者在SparkConf中设置spark.scheduler.allocation.file属性。

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>

conf / fairscheduler.xml.template中也提供了完整的示例。 请注意,未在XML文件中配置的任何池将仅获取所有设置的默认值(调度模式FIFO,权重1和minShare 0)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值