ResourceManager因为块丢失而重启失败

2019-12-06 00:28:14 浏览数 (2)

在非HA情况下,如果HDFS中RM-Restart相关的块丢失,会导致RM无法启动。

RM重启失败日志:

错误日志错误日志

查看查看HDFS丢失块:

该出的块丢失之所以能影响RM的启动,是因为集群默认开启了ResourceManager Restart功能。

ResourceManager Restart

社区对RM重启功能的完善分为两个阶段:

1. 第一阶段(Non-work-preserving RM restart)

     当客户端提交application时,RM会将App的元数据信息(ApplicationSubmissionContext)保存在HDFS中(非HA)或者ZooKeeper(HA集群),同时也会在应用结束时保存应用的最终状态比如完成态(failed, killed, finished)和诊断信息。此外,RM还可以将security keys, tokens保存起来。

    RM重新启动时,它可以从HDFS或者ZooKooper读取这些App的状态信息。RM会对完成状态的APP(failed, killed, finished)和仍在运行中的APP对区分处理:

(1)对于完成态的App,RM仅仅是将保存的信息重新加载到内存中。这么做的典型场景就是在RM重启后,yarn的WEB UI仍然能看到历史的记录任务。

(2)对于运行中的App,RM会将该kill掉APP的ApplicationMaster和container,重新提交该App任务。RM掉线时,NodeManager会一直轮询RM,直到该进程上线。RM复活后会给所有仍在运行的ApplicationMaster,NodeManager发送re-sync命令, 接收到该命令后container和AM会被kill掉,而RM会将会根据保存的App信息,将该App重新启动。

阶段1是在Hadoop2.4.0实现,该阶段的主要问题是:一旦RM重启,所有正在运行中的任务将重新开始跑,对于耗时久的任务来说,这种行为是不可接受的。

2. 第二阶段(Work-preserving RM restart)

    阶段2是在Hadoop2.6.0才开始实现的。主要功能就是在阶段1的基础上增加:RM重启后仍保证运行状态的App继续执行,App可以简单地重新与RM同步,并从停止的地方恢复。

    当NM与重新启动的RM进行同步时,NM不会kill掉container ,而且会将container的状态发送给RM。 RM通过这些container的信息来重建container和对应App的调度状态。与此同时,AM需要将未完成的资源请求重新发送给RM,因为RM在关闭时可能会丢失这些未完成的请求。

ResourceManager Restart Configurations

开启RM重启功能,默认值false:

代码语言:javascript复制
<property>
    <description>Enable RM to recover state after starting. If true, then 
      yarn.resourcemanager.store.class must be specified. </description>
    <name>yarn.resourcemanager.recovery.enabled</name>
    <value>false</value>
</property>

 配置state-store:

代码语言:javascript复制
<property>
    <name>yarn.resourcemanager.store.class</name>
    <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore</value>
</property>

 该参数属性主要使用两类:

(1)org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore,HA集群配置该存储类。

(2)org.apache.hadoop.yarn.server.resourcemanager.recovery.FileSystemRMStateStore,非HA集群配置,将状态信息存储在HDFS。

其他参数可参考官网。

回归到文章开头的问题,在非HA集群中,RM会将App的状态信息存储在${hadoop.tmp.dir}/yarn/system/rmstore路径下,在EMR中该路径就是/data/emr/hdfs/tmp/yarn/system/rmstore/。由于该路径下的/data/emr/hdfs/tmp/yarn/system/rmstore/FSRMStateRoot/EpochNode的块丢失,导致了重启失败。

如下代码,重启时要从这些路径去读取App状态。

代码语言:javascript复制
 protected void serviceStart() throws Exception {
      RMStateStore rmStore = rmContext.getStateStore();
      // The state store needs to start irrespective of recoveryEnabled as apps
      // need events to move to further states.
      rmStore.start();

      if(recoveryEnabled) {
        try {
          LOG.info("Recovery started");
          rmStore.checkVersion();
          if (rmContext.isWorkPreservingRecoveryEnabled()) {       
读取 /data/emr/hdfs/tmp/yarn/system/rmstore/FSRMStateRoot/EpochNode
            rmContext.setEpoch(rmStore.getAndIncrementEpoch());
          }
读取/data/emr/hdfs/tmp/yarn/system/rmstore/FSRMStateRoot/RMAppRoot
          RMState state = rmStore.loadState();
          recover(state);
          LOG.info("Recovery ended");
        } catch (Exception e) {
          // the Exception from loadState() needs to be handled for
          // HA and we need to give up master status if we got fenced
          LOG.error("Failed to load/recover state", e);
          throw e;
        }
      }

      super.serviceStart();
    }

解决方案:

删除这些坏块,RM就能重新启动。HDFS中产生丢失块的大部分原因是没有使用HDFS的命令删除文件,因此为了避免丢失块请使用HDFS的删除命令。

0 人点赞