目录
前面详解了Capacity Scheduler资源调度器,本文描述了FairScheduler,一个Hadoop的可插拔调度程序,它允许yarn应用程序公平地共享大集群中的资源。
1.Fair Scheduler资源队列调度器介绍
公平调度是一种将资源分配给应用程序的方法,这样所有应用程序平均都能在一段时间内获得相同的资源份额。Hadoop NextGen能够调度多种资源类型。默认情况下,公平调度程序只基于内存来安排公平性决策。它可以配置为同时使用内存和CPU进行调度,使用由Ghodsi等人开发的优势资源公平的概念。当有一个应用程序正在运行时,该应用程序将使用整个集群。当提交其他应用程序时,释放的资源被分配给新的应用程序,这样每个应用程序最终获得的资源量大致相同。与默认的Hadoop调度程序不同,它形成了一个应用程序队列,这使得短应用程序能够在合理的时间内完成,而不会让长寿的应用程序挨饿。这也是在多个用户之间共享集群的合理方法。最后,公平共享还可以与应用程序优先级一起工作——优先级被用作权重,以确定每个应用程序应该获得的总资源的比例。
调度程序将应用程序进一步组织成“队列”,并在这些队列之间公平地共享资源。默认情况下,所有用户共享一个名为“默认”的队列。如果应用程序在容器资源请求中专门列出了一个队列,则请求将提交到该队列。还可以通过配置根据请求中包含的用户名分配队列。在每个队列中,调度策略用于在正在运行的应用程序之间共享资源。默认为基于内存的公平共享,但也可以配置具有主导资源公平性的FIFO和多资源。队列可以按层次结构排列以划分资源,并配置权重以按特定比例共享集群。
除了提供公平共享之外,公平调度程序还允许将保证的最小共享分配给队列,这对于确保某些用户、组或生产应用程序始终获得足够的资源非常有用。当队列包含应用程序时,它至少获得其最小共享,但当队列不需要其完全保证共享时,多余的部分将在其他正在运行的应用程序之间进行分割。这使调度程序能够保证队列的容量,同时在这些队列不包含应用程序时有效地利用资源。
Fair Scheduler调度器默认允许所有应用程序运行,但也可以通过配置文件限制每个用户和每个队列运行的应用程序的数量。当用户必须一次提交数百个应用程序时,这可能很有用,或者一般来说,如果一次运行太多的应用程序会导致创建太多中间数据或上下文切换太多,则可以提高性能。限制应用程序不会导致随后提交的任何应用程序失败,只会在计划程序队列中等待,直到用户的某些早期应用程序完成。
2.可插拔策略的分层队列
Fair Scheduler支持分层队列。所有队列都从一个名为“root”的队列下降。可用资源以典型的公平调度方式分布在根队列的子队列中。然后,根队列以同样的方式将分配给他们的资源分配给他们的子队列。只能在叶队列上调度应用程序。通过将队列作为其父队列的子元素放在fair scheduler分配文件中,可以将它们指定为其他队列的子队列。
队列的名称以其父队列的名称开头,句点作为分隔符。因此,根队列下名为“queue1”的队列将被称为“root.queue1”,而名为“parent1”的队列下名为“queue2”的队列将被称为“root.parent1.queue2”。在引用队列时,名称的根部分是可选的,因此queue1可以称为“queue1”,queue2可以称为“parent1.queue2”。
此外,Fair调度程序允许为每个队列设置不同的自定义策略,以允许用户以任何方式共享队列的资源。可以通过扩展org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.scheduling策略来构建自定义策略。Fifopolicy、FairSharePolicy(默认)和DominantResourceFairnessPolicy是内置的,可以随时使用。
然而Fair不支持在已经存在的调度其中添加附加的组件。其中之一是使用自定义策略来控制某些应用程序的优先级“提升”。
3.自动将应用程序放入队列
FairScheduler允许管理员配置自动将提交的应用程序放入适当队列的策略。放置可以取决于提交者的用户和组以及应用程序传递的请求队列。策略由一组规则组成,这些规则按顺序应用以对传入的应用程序进行分类。每个规则要么将应用程序放入队列,要么拒绝它,要么继续执行下一个规则。有关如何配置这些策略,请参阅下面的配置文件。
4.配置启用FairScheduler
要使用fair scheduler,首先在yarn-site.xml中分配适当的scheduler类:
<property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value> </property>
5.队列配置
定制Fair调度程序通常需要修改两个文件。首先,可以通过在现有配置目录的yarn-site.xml文件中添加配置属性来设置调度器范围内的选项。其次,在大多数情况下,用户希望创建一个分配文件,列出存在哪些队列以及它们各自的权重和容量。分配文件每10秒重新加载一次,允许随时进行更改。
5.1可以配置在yarn-site.xml的属性
Property | Description |
yarn.scheduler.fair.allocation.file | 分配文件的路径。分配文件是描述队列及其属性的XML清单,以及某些策略默认值。此文件必须采用下一节中描述的XML格式 。如果给定了相对路径,则会在类路径(通常包括hadoop-conf目录)上搜索该文件。默认为fair-scheduler.xml。 |
yarn.scheduler.fair.user-as-default-queue | 如果未指定队列名称,是否将与分配关联的用户名用作默认队列名称。如果将其设置为“false”或“unset” ,则所有作业都有一个名为“default”的共享默认队列。默认为true。如果在分配文件中给定了队列放置策略,则忽略此属性。 |
yarn.scheduler.fair.preemption | 是否启用抢占,默认为false |
yarn.scheduler.fair.preemption.cluster-utilization-threshold | 开始抢占阈值。利用率计算为所有资源的最大利用率与容量之比。默认为0.8 |
yarn.scheduler.fair.sizebasedweight | 是否根据应用程序的大小将共享分配给各个应用程序,而不是为所有应用程序提供相等的共享,无论大小如何 。当设置为true时,应用程序的权重是1的自然对数加上应用程序请求的总内存,再除以2的自然对数。默认为false。 |
yarn.scheduler.fair.assignmultiple | 是否允许在一个心跳中分配多个容器。默认为false。 |
yarn.scheduler.fair.max.assign | 如果true,可以在一次心跳中分配的容器的最大数量。默认为-1,不设置限制。 |
yarn.scheduler.fair.locality.threshold.node | 对于在特定节点上请求容器的应用程序,指自上次容器分配后在接受另一个节点上的放置之前等待的调度机会数 。表示为介于0和1之间的浮点值,它只是集群大小的一小部分,是要放弃的调度机会数。默认值-1.0表示不要放弃任何计划机会。 |
yarn.scheduler.fair.locality.threshold.rack | 对于在特定节点上请求容器的应用程序,指自上次容器分配后在接受另一节点上的放置之前等待的调度机会数 。表示为介于0和1之间的浮点值,它只是集群大小的一小部分,是要放弃的调度机会数。默认值-1.0表示不要放弃任何计划机会。 |
yarn.scheduler.fair.allow-undeclared-pools | 如果为true,则可以在应用程序提交时创建新队列,无论是因为提交者将它们指定为应用程序队列 ,还是因为用户将它们作为默认队列属性放置在那里。如果该值为false, 则每当应用程序被放置在未在分配文件中指定的队列中时,它都会被放置在“默认”队列中。默认为true。 如果在分配文件中给定了队列放置策略,则忽略此属性。 |
yarn.scheduler.fair.update-interval-ms | 锁定调度程序并重新计算公平份额、重新计算需求以及检查是否有任何应优先抢占的间隔。默认为500 ms。 |
5.2队列配置文件格式
配置文件必须为XML格式。格式包含五种类型的元素:
queue: 代表队列。队列元素可以采用可选属性“type”,当设置为“parent”时,它将成为父队列。当我们希望在不配置任何叶队列的情况下创建父队列时,这非常有用。每个队列元素可以包含以下属性:
fairSharePreemptionThreshold: 队列的公平共享抢占阈值。如果队列等待fairsharepreemptionTimeout而未收到fairsharepreemptionThreshold*fairshare资源,则允许抢占容器以从其他队列获取资源。如果未设置,则队列将从其父队列继承值.
fairSharePreemptionTimeout: 队列在试图抢占容器以从其他队列获取资源之前处于公平共享阈值之下的秒数。也就是超过这个时间秒数之前,我要抢占到权重指定的资源,如果未设置,则队列将从其父队列继承值.
minSharePreemptionTimeout: 队列在尝试抢占容器以从其他队列获取资源之前处于其最小共享之下的秒数。获取最低资源的超时时间,如果未设置,则队列将从其父队列继承值.
aclAdministerApps: 可以管理队列的用户和/或组的列表。当前唯一的管理操作是终止应用程序。有关此列表的格式以及队列ACL如何工作的详细信息,请参阅下面的acls部分。.
aclSubmitApps: 可以向队列提交应用程序的用户和/或组的列表。有关此列表的格式以及队列ACL如何工作的详细信息,请参阅下面的acls部分。.
schedulingPolicy:设置任何队列的调度策略。允许的值为“fifo”/“fair”/“drf”或任何扩展org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.scheduling策略的类。默认为“fair”。如果“FIFO”,提交时间较早的应用程序优先获取容器,但如果满足较早应用程序的请求后集群上有剩余空间,则稍后提交的应用程序可能同时运行。.
weight: 与其他队列不成比例地共享集群。权重默认为1,权重为2的队列接收的资源大约是默认权重队列的两倍。.
maxAMShare: 限制可用于运行应用程序主服务器的队列公平共享的部分。此属性只能用于叶队列。例如,如果设置为1.0f,那么叶队列中的AMS可以占用内存和CPU公平共享的100%。值-1.0f将禁用此功能,并且不会检查amshare。默认值为0.5f.
maxRunningApps: 限制队列中要同时运行的应用程序数
maxResources: 允许队列的最大资源量,格式为“x MB,y vcores”。对于单资源公平策略,vcores值被忽略。永远不会为队列分配将其聚合使用量超过此限制的容器资源。.
minResources: 队列有权使用的最小资源,格式为“x MB,y vcores”。对于单资源公平策略,vcores值被忽略。如果一个队列的最小共享不满足,那么它将在同一父队列下的任何其他队列之前提供可用资源。在单资源公平性策略下,如果队列的内存使用量低于其最小内存共享量,则认为该队列不满足要求。在显性资源公平性下,如果队列对其相对于集群容量的显性资源的使用低于其对该资源的最小共享,则认为该队列不满足要求。如果在这种情况下不满足多个队列,那么资源将以相关资源使用率和最小值之间的最小比率进入队列。请注意,在提交应用程序时,低于其最小值的队列可能不会立即达到其最小值,因为已经运行的作业可能正在使用这些资源。.
user: 它表示控制单个用户行为的设置。它们可以包含一个属性:maxrunningapps,这是对特定用户正在运行的应用程序数量的限制。
userMaxAppsDefault : 它为未另行指定限制的任何用户设置默认的运行应用程序限制.
defaultFairSharePreemptionTimeout : 为根队列设置公平共享抢占超时;由根队列中的fairsharepreemptionTimeout元素重写.
defaultMinSharePreemptionTimeout : 为根队列设置最小共享抢占超时;由根队列中的minSharePreemptionTimeout 抢占超时元素重写.
defaultFairSharePreemptionThreshold : 它为根队列设置公平共享抢占阈值;由根队列中的fairSharePreemptionThreshold 元素重写.
queueMaxAppsDefault : 它为队列设置默认的运行应用程序限制;由每个队列中的maxRunningApps元素覆盖.
queueMaxAMShareDefault : 它为队列设置默认AM资源限制;由每个队列中的maxAMShare 元素覆盖。
defaultQueueSchedulingPolicy : 它为队列设置默认的调度策略;如果指定,则由每个队列中的schedulingPolicy 元素覆盖。默认为“fair”.
queuePlacementPolicy : 其中包含一个规则元素列表,告诉调度程序如何将传入的应用程序放入队列。规则按列出的顺序应用。规则可以采用参数。所有规则都接受“create”参数,该参数指示规则是否可以创建新队列。“create”默认值为true;如果设置为false,并且规则会将应用程序放置在未在分配文件中配置的队列中,我们将继续执行下一个规则。最后一条规则必须是永远不能发出continue的规则。有效规则是:
reject: 应用程序被拒绝.
default: 将应用程序放入默认规则的“queue”属性中指定的队列中。如果未指定“queue”属性,则将应用程序放入“root.default”队列.
nestedUserQueue : 将应用程序放入一个队列中,该队列的用户名位于嵌套规则建议的队列下。这类似于“user”规则,不同之处在于“nestedUserQueue ”规则,用户队列可以在任何父队列下创建,而“user”规则仅在根队列下创建用户队列。请注意,只有当嵌套规则返回父队列时,才会应用NestedUserQueue规则。可以通过将队列的“type”属性设置为“parent”或配置该队列下至少一个使其成为父队列的叶来配置父队列。参见示例用例的分配.
secondaryGroupExistingQueue:该应用程序被放入一个队列,其名称与提交该应用程序的第二个用户组相匹配。将选择与已配置队列匹配的第一个辅助组。组名中的句点将被替换为“_dot_”,即,如果存在这样的队列,则将一个具有“one.two”作为其辅助组之一的用户放入“one_dot_two”队列。.
primaryGroup: 该应用程序将被放入一个队列,其中包含提交它的用户的主要组的名称。组名中的句点将替换为“_dot_”,即“one.two”组的队列名称为“one_dot_two”。
user: 这个应用程序被放入一个队列,队列中有提交它的用户的名字。用户名中的句点将替换为“_dot_”,即用户“first.last”的队列名称是“first_dot_last”.
specified:应用程序被放入它请求的队列中。如果应用程序没有请求队列,即它指定了“default”,我们继续。如果应用程序请求以句点开头或结尾的队列名称,即“.q1”或“q1.”等名称将被拒绝。
5.3案例配置
<?xml version="1.0"?> <allocations> <queue name="sample_queue"> <minResources>10000 mb,0vcores</minResources> <maxResources>90000 mb,0vcores</maxResources> <maxRunningApps>50</maxRunningApps> <maxAMShare>0.1</maxAMShare> <weight>2.0</weight> <schedulingPolicy>fair</schedulingPolicy> <queue name="sample_sub_queue"> <aclSubmitApps>charlie</aclSubmitApps> <minResources>5000 mb,0vcores</minResources> </queue> </queue> <queueMaxAMShareDefault>0.5</queueMaxAMShareDefault> <!-- Queue 'secondary_group_queue' is a parent queue and may have user queues under it --> <queue name="secondary_group_queue" type="parent"> <weight>3.0</weight> </queue> <user name="sample_user"> <maxRunningApps>30</maxRunningApps> </user> <userMaxAppsDefault>5</userMaxAppsDefault> <queuePlacementPolicy> <rule name="specified" /> <rule name="primaryGroup" create="false" /> <rule name="nestedUserQueue"> <rule name="secondaryGroupExistingQueue" create="false" /> </rule> <rule name="default" queue="sample_queue"/> </queuePlacementPolicy> </allocations>
注意,为了与最初的fairscheduler向后兼容,可以将“queue”元素命名为“pool”元素。
5.4队列访问控制列表
队列访问控制列表(ACL)允许管理员控制哪些人可以对特定队列执行操作。它们配置了aclSubmitApps 和aclAdministerApps属性,可以为每个队列设置这些属性。当前唯一支持的管理操作是终止应用程序。任何可能管理队列的人也可以向队列提交申请。这些属性以“user1,user2 group1,group2”或“group1,group2”等格式获取值。如果队列的用户或组位于该队列的ACL或该队列的任何祖先的ACL中,则允许对该队列执行操作。因此,如果queue2在queue1中,而user1在queue1的acl中,而user2在queue2的acl中,则两个用户都可以提交到queue2。
注意:分隔符是空格字符。要仅指定ACL组,请以空格字符开头。
根队列的acl默认为“*”,因为acl是向下传递的,这意味着每个人都可以提交到每个队列,并杀死其中的应用程序。要开始限制访问,请将根队列的ACL更改为“*”以外的其他值。
6.调度器管理
Fair调度程序通过以下几种机制为运行时的管理提供支持:
6.1运行时修改配置
通过编辑分配文件,可以在运行时修改最小共享、限制、权重、抢占超时和队列调度策略。调度程序将在看到该文件被修改10-15秒后重新加载该文件。
6.2通过Web UI监控
当前的应用程序、队列和公平共享可以通过ResourceManager的Web界面(http://*ResourceManager URL*/cluster/scheduler)进行检查。
对于Web界面上的每个队列,可以看到以下字段:
Used Resources - 分配给队列中容器的资源的总和.
Num Active Applications - 队列中已接收至少一个容器的应用程序数.
Num Pending Applications - 队列中尚未接收任何容器的应用程序数.
Min Resources -为队列提供保证的配置的最小资源.
Max Resources - 配置的允许进入队列的最大资源数.
Instantaneous Fair Share - 队列的即时公平资源共享。这些共享只考虑活动队列(那些运行应用程序的队列),并用于调度决策。当其他队列不使用这些资源时,可以将这些资源分配到其共享之外。资源消耗处于或低于其即时公平份额的队列永远不会抢占其容器。.
Steady Fair Share - 队列中稳定的公平资源份额。这些共享考虑所有队列,而不管它们是否处于活动状态(具有正在运行的应用程序)。它们的计算频率较低,只有在配置或容量发生变化时才会发生变化。它们旨在提供用户可以期望的资源的可视性,从而显示在Web UI中。.
6.3在队列之间移动应用程序
Fair调度程序支持将正在运行的应用程序移动到其他队列。这对于将重要应用程序移动到更高优先级队列,或将不重要的应用程序移动到较低优先级队列很有用。可以通过运行yarn应用程序-movetoqueue appid-queue targetqueuename来移动应用程序。
当应用程序移动到队列时,为了确定公平性,它的现有分配将被计算为新队列的分配,而不是旧队列的分配。如果将应用程序的资源添加到队列将违反其maxrunningapps或maxresources约束,则将应用程序移动到队列的尝试将失败。
7.配置案例
我的目的是配置三个队列,除了权重不一样,大家都可以互相抢占,实现资源弹性最大利用率
7.1yarn-site.xml
启用fair队列并开启抢占
<property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value> </property> <property> <name>yarn.scheduler.fair.preemption</name> <value>true</value> </property>
7.2fair-scheduler.xml
配置三个队列,fair-scheduler.xml,我是复制hadoop-2.7.7/share/hadoop/tools/sls/sample-conf/fair-scheduler.xml,修改了丢到etc/hadoop中的
<allocations> <userMaxAppsDefault>1000</userMaxAppsDefault> <queue name="high"> <schedulingMode>fair</schedulingMode> <weight>5</weight> <minSharePreemptionTimeout>1</minSharePreemptionTimeout> <fairSharePreemptionTimeout>2</fairSharePreemptionTimeout> <fairSharePreemptionThreshold>0.8</fairSharePreemptionThreshold> </queue> <queue name="middle"> <schedulingMode>fair</schedulingMode> <weight>3</weight> <minSharePreemptionTimeout>100</minSharePreemptionTimeout> <fairSharePreemptionTimeout>200</fairSharePreemptionTimeout> <fairSharePreemptionThreshold>0.4</fairSharePreemptionThreshold> </queue> <queue name="low"> <schedulingMode>fair</schedulingMode> <weight>2</weight> <minSharePreemptionTimeout>1000</minSharePreemptionTimeout> <fairSharePreemptionTimeout>2000</fairSharePreemptionTimeout> <fairSharePreemptionThreshold>0.2</fairSharePreemptionThreshold> </queue>
7.3 web界面查看效果
master:8088/cluster/scheduler
最后如果是spark程序使用队列,spark-submit指定--queue参数就可以了,队列名直接使用最后的节点的名字就可以了。