2.Yarn基础_工作原理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_15014327/article/details/83033545

一.Yarn调度流程

1.Client向YARN提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等。

2.ResourceManager为Job分配第一个Container,并与Container所在的NodeManager通信,要求NodeManager在这个Container中启动该作业的ApplicationMaster。

3.NodeManager启动一个Container运行ApplicationMaster。

4.ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceManager查询该作业的运行状态;然后它将为各个任务申请资源并监控任务的运行状态。如果Container没有完全申请到位,则会先使用已经分配到位的部分Container资源进行后续的(5,6,7)步骤,其余Container部分由ApplicationMaster采用轮询的方式通过RPC请求向ResourceManager申请和领取资源,直到全部资源分配到位。

5.一旦ApplicationMaster申请到Container资源后,便与资源所在的NodeManager通信,要求NodeManager启动任务。6.NodeManager执行ApplicationMaster发送的命令,启动Container任务。

7.各个Container通过RPC向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。

8.作业完成后,ApplicationMaster向ResourceManager申请注销并关闭自己。

二.Yarn调度策略

1.容器调度

为多个用户提供一个共享集群,每个用户分配专门的资源队列。主要特征:分层队列、容量保证、安全性、弹性 、多租户、可操作性、基于资源的调度、基于用户或组的队列映射 。

设置ResourceManager使用CapacityScheduler

yarn-site.xml:

yarn.resourcemanager.scheduler.class org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler

设置队列

capacity-scheduler.xml:

<property> 
  <name>yarn.scheduler.capacity.root.queues</name> 
  <value>a,b,c</value> 
  <description>此级别的队列(root是根队列)</description> 
</property> 
<property> 
  <name>yarn.scheduler.capacity.root.a.queues</name> 
  <value>a1,a2</value> 
  <description>此级别的队列(root)是根队列</description> 
</property> 
<property> 
  <name>yarn.scheduler.capacity.root.b.queues</name> 
  <value>b1,b2,b3</value> 
  <description>此级别的队列(root是根队列)</description> 
</property>

队列属性

  • 资源分配
    yarn.scheduler.capacity<queue-path>.capacity 容量百分比(%)排队为浮点数(例如12.5)。每个级别的所有队列的容量总和必须等于100.如果有空闲资源,则队列中的应用程序可能比队列容量消耗更多资源,从而提供弹性。
    yarn.scheduler.capacity<queue-path>.maximum-capacity 最大队列容量,以百分比(%)表示为浮点数。这限制了队列中应用程序的弹性。默认为-1,禁用它。
    yarn.scheduler.capacity<queue-path>.minimum-user-limit-percent 如果存在资源需求,则每个队列对在任何给定时间分配给用户的资源百分比强制实施限制。用户限制可以在最小值和最大值之间变化。前者(最小值)设置为此属性值,后者(最大值)取决于已提交应用程序的用户数。例如,假设此属性的值为25.如果两个用户已将应用程序提交到队列,则任何单个用户都不能使用超过50%的队列资源。如果第三个用户提交应用程序,则任何单个用户都不能使用超过33%的队列资源。对于4个或更多用户,没有用户可以使用超过25%的队列资源。值100表示​​不强加用户限制。默认值为100.值指定为整数。
    yarn.scheduler.capacity.<queue-path>.user-limit-factor 队列容量的倍数,可以配置为允许单个用户获取更多资源。默认情况下,此值设置为1可确保单个用户永远不会超过队列配置的容量,无论群集的空闲程度如何。值被指定为float。
    yarn.scheduler.capacity.<queue-path>.maximum-allocation-mb 每个队列在资源管理器上分配给每个容器请求的最大内存限制。此设置将覆盖群集配置yarn.scheduler.maximum-allocation-mb。该值必须小于或等于群集最大值。
    yarn.scheduler.capacity.<queue-path>.maximum-allocation-vcores 在资源管理器中分配给每个容器请求的虚拟核心的每个队列最大限制。此设置将覆盖群集配置yarn.scheduler.maximum-allocation-vcores。该值必须小于或等于群集最大值。
  • 队列管理和权限
    yarn.scheduler.capacity.<queue-path>.state 队列的状态。可以是RUNNING或STOPPED之一。如果队列处于STOPPED状态,则无法将新应用程序提交给自身或其任何子队列。因此,如果根队列是STOPPED,则不能将任何应用程序提交给整个群集。现有应用程序继续完成,因此可以优雅地排空队列。值指定为枚举。
    yarn.scheduler.capacity.root.<queue-path>.acl_submit_applications 控制谁可以将应用程序提交到给定队列的ACL。如果给定用户/组在给定队列上具有必要的ACL,或者在层次结构中具有一个父队列,则他们可以提交应用程序。ACL的该属性是从父队列继承如果没有指定。
    yarn.scheduler.capacity.root.<queue-path>.acl_administer_queue 用于控制谁可以管理给定队列上的应用程序的ACL。如果给定用户/组在给定队列上具有必要的ACL,或者在层次结构中具有一个父队列,则它们可以管理应用程序。ACL的该属性是从父队列继承如果没有指定。
    注:一个访问控制列表的形式为user1,user2spacegroup1,group2。*代表任何user。如果未指定,则根队列的默认值为*。
  • 基于用户或组的队列映射
    yarn.scheduler.capacity.queue-mappings 此配置指定用户或组到特定队列的映射。您可以将单个用户或用户列表映射到队列。语法:[u或g]:[name]:[queue_name] [,next_mapping] *。这里,u或g表示映射是针对用户还是组。用户的值为u,组的值为g。name表示用户名或组名。要指定已提交应用程序的用户,可以使用%user。queue_name表示应用程序必须映射到的队列名称。要指定与用户名相同的队列名称,可以使用%user。要指定与用户所属的主要组的名称相同的队列名称,可以使用%primary_group。
    yarn.scheduler.capacity.queue-mappings-override.enable 此函数用于指定是否可以覆盖用户指定的队列。这是一个布尔值,默认值为false。
    Example:
    
    <property>
       <name>yarn.scheduler.capacity.queue-mappings</name>
       <value>u:user1:queue1,g:group1:queue2,u:%user:%user,u:user2:%primary_group</value>
       <description>
            <user1>映射到<queue1>,<group1>映射到<queue2>,
            将user映射到与user同名的队列,<user2>映射到与<primary_group>队列名相同的队列。
            从左到右评估映射,并将使用第一个有效映射。
       </description>
     </property>

    更改队列配置

  • 编辑conf/capacity-scheduler.xml并运行yarn rmadmin -refreshQueues。
    vi capacity-scheduler.xml 
    bin/yarn rmadmin -refreshQueues

    注意:无法删除队列,仅支持添加新队列

2.公平调度

公平调度是一种为应用程序分配资源的方法,使得所有应用程序平均可以随时间获得相等的资源份额。默认情况下,公平调度程序仅根据内存来确定调度公平性决策。调度程序将应用程序进一步组织为“队列”,并在这些队列之间公平地共享资源。默认情况下,所有用户共享一个名为“default”的队列。如果应用程序专门在容器资源中请求某个队列,就将得到该队列资源。

配置ResourceManager使用公平调度

yarn-site.xml:

<property> 
  <name>yarn.resourcemanager.scheduler.class</name> 
  <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value> 
</property>

配置公平调度

在大多数情况下,用户需要创建一个分配文件,列出存在哪些队列及其各自的权重和容量。

yarn.scheduler.fair.allocation.file 分配文件的路径。除了某些策略默认值之外,分配文件是描述队列及其属性的XML清单。此文件必须采用XML格式。如果给出了相对路径,则在类路径上搜索文件。
yarn.scheduler.fair.user-as-default-queue 在未指定队列名称的情况下,将为用户分配default队列。如果将其设置为“false”或未设置,则所有作业都具有共享的默认队列,名为"default"。默认为true。如果在分配文件中给出了队列放置策略,则忽略此属性。
yarn.scheduler.fair.preemption 是否使用抢占,默认为false。
yarn.scheduler.fair.preemption.cluster-utilization-threshold 抢占后的利用率阈值。利用率计算为所有资源中使用量与容量的最大比率。默认为0.8f。
yarn.scheduler.fair.sizebasedweight 根据个人应用的大小分配份额,而不是为所有应用提供相同的份额。设置为true时,应用程序按自然对数加上应用程序的总和除以自然对数2求内存加权。默认为false。
yarn.scheduler.fair.assignmultiple 是否允许在一个心跳中进行多个容器分配。默认为false。
yarn.scheduler.fair.max.assign 如果assignmultiple为true,则可以在一个心跳中分配的最大容器数量。默认为-1,设置无限制。
yarn.scheduler.fair.locality.threshold.node 对于在特定节点上请求容器的应用程序,自上次容器分配以来在接受另一个节点上的放置之前等待的调度机会数。表示为0到1之间的浮点数,它作为簇大小的一部分,是要传递的调度机会的数量。默认值-1表示没有调度机会数。
yarn.scheduler.fair.locality.threshold.rack 对于在特定机架上请求容器的应用程序,自上次容器分配以来在接受另一个节点上的放置之前等待的调度机会数。表示为0到1之间的浮点数,它作为簇大小的一部分,是要传递的调度机会的数量。默认值-1表示没有调度机会数。
yarn.scheduler.fair.allow-undeclared-pools 如果是这样,则可以在应用程序提交时创建新队列,无论是因为提交者将它们指定为应用程序的队列,还是因为user-as-default-queue属性将它们放在那里。如果这是错误的,则只要将应用程序放置在未在分配文件中指定的队列中,就会将其置于"default"队列中。默认为true。如果在分配文件中给出了队列放置策略,则忽略此属性。
yarn.scheduler.fair.update-interval-ms 锁定调度程序并重新计算公平份额的间隔,重新计算需求,并检查是否有任何事项应该抢占。默认为500毫秒。

分配文件格式

分配文件必须是XML格式。该格式包含五种类型的元素:

  • 队列元素:代表队列。队列元素可以采用可选属性“类型”,当设置为“父”时,它将使其成为父队列。当我们想要创建父队列而不配置任何叶队列时,这非常有用。每个队列元素可能包含以下属性:

    • minResources:队列有权获得的最小资源,格式为“X mb,Y vcores”。对于单资源公平性策略,将忽略vcores值。如果不满足队列的最小份额,则将在同一父节点下的任何其他队列之前提供可用资源。在单资源公平策略下,如果队列的内存使用率低于其最小内存份额,则认为队列不满意。在主导资源公平性下,如果队列的主导资源相对于群集容量的使用低于其对该资源的最小份额,则认为该队列不满意。如果在这种情况下多个队列不满足,则资源将以相关资源使用率与最小值之间的最小比率进入队列。
    • maxResources:允许队列的最大资源,格式为“X mb,Y vcores”。对于单资源公平性策略,将忽略vcores值。永远不会为队列分配一个容器,将其聚合使用量超过此限制。
    • maxRunningApps:限制队列中的应用程序一次运行
    • maxAMShare:限制可用于运行应用程序主服务器的队列公平共享的分数。此属性只能用于叶队列。例如,如果设置为1.0f,那么叶队列中的AM最多可占用内存和CPU公平份额的100%。-1.0f的值将禁用此功能,并且不会检查amShare。默认值为0.5f。
    • weight:与其他队列不成比例地共享群集。权重默认为1,权重为2的队列应该接收的资源大约是具有默认权重的队列的两倍。
    • schedulingPolicy:设置任意队列的调度策略。允许的值为“fifo”/“fair”/“drf”或任何扩展org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.SchedulingPolicy的类。默认为“合理”。如果“fifo”,具有较早提交时间的应用程序将优先考虑容器,但如果在满足早期应用程序的请求后群集上有剩余空间,则稍后提交的应用程序可以同时运行。
    • aclSubmitApps:可以将应用程序提交到队列的用户和/或组的列表。有关此列表格式以及队列ACL如何工作的详细信息,请参阅下面的ACL部分。
    • aclAdministerApps:可以管理队列的用户和/或组的列表。目前唯一的管理操作是终止应用程序。有关此列表格式以及队列ACL如何工作的详细信息,请参阅下面的ACL部分。
    • minSharePreemptionTimeout:队列在尝试抢占容器以从其他队列中获取资源之前,队列处于其最小份额之下的秒数。如果未设置,队列将从其父队列继承该值。
    • fairSharePreemptionTimeout:队列在尝试抢占容器以从其他队列中获取资源之前,队列处于其公平共享阈值之下的秒数。如果未设置,队列将从其父队列继承该值。
    • fairSharePreemptionThreshold:队列的公平共享抢占阈值。如果队列在没有收到fairSharePreemptionThreshold * fairShare资源的情况下等待fairSharePreemptionTimeout,则允许它抢占容器以从其他队列获取资源。如果未设置,队列将从其父队列继承该值。
  • 用户元素:表示管理各个用户行为的设置。它们可以包含单个属性:maxRunningApps,对特定用户正在运行的应用程序数量的限制。

  • userMaxAppsDefault元素:为未以其他方式指定限制的任何用户设置默认运行应用程序限制。

  • defaultFairSharePreemptionTimeout元素:用于设置根队列的公平共享抢占超时; 被根队列中的fairSharePreemptionTimeout元素覆盖。

  • defaultMinSharePreemptionTimeout元素:设置根队列的最小共享抢占超时; 被根队列中的minSharePreemptionTimeout元素覆盖。

  • defaultFairSharePreemptionThreshold元素:设置根队列的公平共享抢占阈值; 被根队列中的fairSharePreemptionThreshold元素覆盖。

  • queueMaxAppsDefault元素:设置队列的默认运行应用限制; 由每个队列中的maxRunningApps元素覆盖。

  • queueMaxAMShareDefault元素:设置队列的默认AM资源限制; 由每个队列中的maxAMShare元素覆盖。

  • defaultQueueSchedulingPolicy元素:设置队列的默认调度策略; 如果指定,则由每个队列中的schedulingPolicy元素覆盖。默认为“合理”。

  • queuePlacementPolicy元素:包含一个规则元素列表,告诉调度程序如何将传入的应用程序放入队列。规则按列出的顺序应用。规则可能需要参数。所有规则都接受“create”参数,该参数指示规则是否可以创建新队列。“创建”默认为true; 如果设置为false并且规则将应用程序放在未在分配文件中配置的队列中,我们将继续执行下一个规则。最后一条规则必须是永远不会发出继续的规则。有效规则是:

    • 指定队列:将应用程序放入其请求的队列中。如果应用程序请求没有队列,即它指定“默认”,我们继续。如果应用程序请求以句点开头或结尾的队列名称,则将拒绝诸如“.q1”或“q1。”之类的名称。
    • user:将应用程序放入一个队列,其中包含提交它的用户的名称。用户名中的句点将替换为“_dot_”,即用户“first.last”的队列名称为“first_dot_last”。
    • primaryGroup:将应用程序放入一个队列,其中包含提交它的用户的主要组的名称。组名称中的句点将替换为“_dot_”,即组“one.two”的队列名称为“one_dot_two”。
    • secondaryGroupExistingQueue:将应用程序放入队列中,其名称与提交它的用户的辅助组相匹配。将选择与已配置队列匹配的第一个辅助组。组名称中的句点将替换为“_dot_”,即如果存在这样的队列,则将具有“one.two”作为其一个辅助组的用户放入“one_dot_two”队列中。
    • nestedUserQueue:将应用程序放入队列中,其中包含嵌套规则建议的队列下的用户名。这类似于“用户”规则,区别在于“nestedUserQueue”规则,用户队列可以在任何父队列下创建,而“user”规则仅在根队列下创建用户队列。请注意,仅当嵌套规则返回父队列时才会应用nestedUserQueue规则。可以通过将queue的'type'属性设置为'parent'或通过在该队列下配置至少一个叶子来配置父队列,这使得它成为家长。请参阅示例用例的示例分配。
    • default:将应用程序放入默认规则的'queue'属性中指定的队列中。如果未指定“queue”属性,则将应用程序置于“root.default”队列中。
    • 拒绝的应用:该应用被拒绝。
<?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>

队列访问控制列表

队列访问控制列表(ACL)允许管理员控制可以对特定队列执行操作的人员。它们配置了aclSubmitApps和aclAdministerApps属性,可以为每个队列设置。目前唯一支持的管理操作是终止应用程序。任何可能管理队列的人也可以向其提交申请。这些属性采用"user1,user2 group1,group2"或“group1,group2”等格式的值。如果队列中的用户或组位于该队列的ACL中或该队列中任何一个祖先的ACL中,则允许对该队列执行操作。因此,如果queue2在queue1中,并且user1在queue1的ACL中,并且user2在queue2的ACL中,则两个用户都可以提交到queue2。

注意:分隔符是空格字符。要仅指定ACL组,请使用空格字符开始值。

默认情况下,根队列的ACL为"*",因为ACL向下传递意味着每个人都可以从每个队列提交并终止应用程序。要开始限制访问,请将根队列的ACL更改为"*"以外的其他值。

三.ResourceManager HA

ResourceManager(RM)负责跟踪集群中的资源,以及调度应用程序(例如:MapReduce作业)。在Hadoop 2.4之前,ResourceManager是YARN集群中的单点故障。高可用性功能以Active/Standby ResourceManager的形式添加冗余,以消除此单点故障。

1. ResourceManager HA设计

2.ResourceManager故障转移

ResourceManager HA通过主动/备用架构实现 在任何时间点,其中一个RM处于active状态,并且一个或多个RM处于standby模式。等active RM出现故障时,standby RM接管。

  • 手动转换和故障转移
    • 如果未启用自动故障转移,则管理员必须手动将其中一个RM转换为活动。要从一个RM故障转移到另一个RM,他们应该首先将Active-RM转换为待机状态,并将Standby-RM转换为Active。所有这些都可以使用"yarn rmadmin"完成。
  • 自动故障转移
    • RM可以选择嵌入基于Zookeeper的ActiveStandbyElector来决定哪个RM应该是Active。当Active关闭或无响应时,另一个RM自动被选为Active,然后接管。请注意,不需要像HDFS那样运行单独的ZKFC守护程序,因为嵌入在RM中的ActiveStandbyElector充当故障检测器和领导者选择器而不是单独的ZKFC守护程序。
  • RM故障转移相关Clinet、AM和NM

    • 当存在多个RM时,客户端和节点使用的配置(yarn-site.xml)应该列出所有RM。Client、AM、NM尝试以循环方式连接到RM,直到它们到达Active RM。如果Active停止,他们将进行轮询,直到他们到达Active RM。此默认重试逻辑实现为org.apache.hadoop.yarn.client.ConfiguredRMFailoverProxyProvider。也可以用下面的类覆盖默认逻辑,实现org.apache.hadoop.yarn.client.RMFailoverProxyProvider并设置值为yarn.client.failover-proxy-provider。

3.ResourceManager HA配置

yarn.resourcemanager.zk-address ZK-quorum的地址。用于active RM选举。
yarn.resourcemanager.ha.enabled 启用RM HA。
yarn.resourcemanager.ha.rm-ids RM的逻辑ID列表。例如,“rm1,rm2”。
yarn.resourcemanager.hostname。rm-id 对于每个rm-id,指定RM对应的主机名。或者,可以设置每个RM的服务地址。
yarn.resourcemanager.address。rm-id 对于每个rm-id,请为客户端指定host:port以提交作业。如果设置,则覆盖yarn.resourcemanager.hostname中设置的主机名。rm-id。
yarn.resourcemanager.scheduler.address。rm-id 对于每个rm-id,为ApplicationMaster指定scheduler host:port以获取资源。如果设置,则覆盖yarn.resourcemanager.hostname中设置的主机名。rm-id。
yarn.resourcemanager.resource-tracker.address。rm-id 对于每个rm-id,指定要连接的NodeManagers的host:port。如果设置,则覆盖yarn.resourcemanager.hostname中设置的主机名。rm-id。
yarn.resourcemanager.admin.address。rm-id 对于每个rm-id,请为管理命令指定host:port。如果设置,则覆盖yarn.resourcemanager.hostname中设置的主机名。rm-id。
yarn.resourcemanager.webapp.address。rm-id 对于每个rm-id,指定RM Web应用程序的host:port对应。如果将yarn.http.policy设置为HTTPS_ONLY,则不需要此选项。如果设置,则覆盖yarn.resourcemanager.hostname中设置的主机名。rm-id。
yarn.resourcemanager.webapp.https.address。rm-id 对于每个rm-id,指定RM https Web应用程序对应的host:port。如果将yarn.http.policy设置为HTTP_ONLY,则不需要此项。如果设置,则覆盖yarn.resourcemanager.hostname中设置的主机名。rm-id。
yarn.resourcemanager.ha.id 识别整体中的RM。这是可选的; 但是,如果设置,管理员必须确保所有RM在配置中都有自己的ID。
yarn.resourcemanager.ha.automatic-failover.enabled 启用自动故障转移; 默认情况下,仅在启用HA时启用它。
yarn.resourcemanager.ha.automatic-failover.embedded 启用自动故障转移时,使用嵌入式leader-elector选择Active RM。默认情况下,仅在启用HA时启用它。
yarn.resourcemanager.cluster-id 标识集群。由选民使用以确保RM不会接管另一个群集的Active。
yarn.client.failover-proxy-provider 客户端,AM和NM用于故障转移到Active RM的类。
yarn.client.failover-max-attempts FailoverProxyProvider应尝试进行故障转移的最大次数。
yarn.client.failover-sleep-base-ms 用于计算故障转移之间的指数延迟的睡眠基数(以毫秒为单位)。
yarn.client.failover-sleep-max-ms 故障转移之间的最长休眠时间(以毫秒为单位)。
yarn.client.failover-retries 每次尝试连接到ResourceManager的重试次数。
yarn.client.failover-retries-on-socket-timeouts 每次尝试连接到套接字超时上的ResourceManager的重试次数。
<property>
  <name>yarn.resourcemanager.ha.enabled</name>
  <value>true</value>
</property>
<property>
  <name>yarn.resourcemanager.cluster-id</name>
  <value>cluster1</value>
</property>
<property>
  <name>yarn.resourcemanager.ha.rm-ids</name>
  <value>rm1,rm2</value>
</property>
<property>
  <name>yarn.resourcemanager.hostname.rm1</name>
  <value>master1</value>
</property>
<property>
  <name>yarn.resourcemanager.hostname.rm2</name>
  <value>master2</value>
</property>
<property>
  <name>yarn.resourcemanager.webapp.address.rm1</name>
  <value>master1:8088</value>
</property>
<property>
  <name>yarn.resourcemanager.webapp.address.rm2</name>
  <value>master2:8088</value>
</property>
<property>
  <name>yarn.resourcemanager.zk-address</name>
  <value>zk1:2181,zk2:2181,zk3:2181</value>
</property>

管理命令

yarn rmadmin有一些特定于HA的命令选项来检查RM的运行状况和状态,并转换为Active/Standby。HA的命令将yarn.resourcemanager.ha.rm-ids设置的RM service id作为参数。

$ yarn rmadmin -getServiceState rm1 
 active 

$ yarn rmadmin -getServiceState rm2 
 standby

猜你喜欢

转载自blog.csdn.net/qq_15014327/article/details/83033545