Home > Archives > Hadoop基础之ResourceManager重启过程中的恢复机制

Hadoop基础之ResourceManager重启过程中的恢复机制

Published on

周五的时候,向Hadoop集群提交了一个任务,运行的过程中ResourceManager进程由于某些原因突然中止了。通过yarn-daemon.sh start resourcemanager命令重启之后,发现之前的应用仍然顺利执行。猜想可能是由于ResourceManager重启恢复的某种机制才能保证了应用的继续运行。通过官网中的ResourceManger Restart找到一些答案,现整理如下。

重启过程

为了降低ResourceManager重启带来的影响,它就必须在正常运行时去记录一些状态信息,这样在重启之后才能去获取并且构造对应状态的实例。这个过程经历了两个阶段的发展:

基本配置

为了存储应用元数据,我们需要使用一些可靠的外部存储系统,比如说Zookeeper、HDFS还有官网中提到的LevelDB。下面主要介绍Zoookeeper的相关配置:

    <property>
        <name>yarn.resourcemanager.recovery.enabled</name>
        <value>true</value>
    </property>
    <property>
        <name>yarn.resourcemanager.store.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
    </property>
    <property>
        <name>yarn.resourcemanager.zk-address</name>
        <!--如果是集群则可以配置多个,以逗号分隔-->
        <value>localhost:2181</value>
    </property>

在应用运行的过程中,我们也可以通过查看Znode的结构来验证状态是否被存储。

# zk-shell localhost:2181 --run-once tree

├── rmstore
│   ├── ZKRMStateRoot
│   │   ├── RMAppRoot
│   │   │   ├── application_1491640108912_0001
│   │   │   │   ├── appattempt_1491640108912_0001_000001
...

通过ZKRMStateRoot键我们可以确认,ResourceManager的信息已经被存储。

实际操作

在验证的过程中(伪分布式集群模式 - Pseudodistributed mode,Hadoop 2.7.2),我们可以先启动应用,等它进行RUNNING状态之后, 通过yarn-daemon.sh stop resourcemanager命令杀掉ResourceManager进程,这时候可以看到Client会尝试重连ResourceManager Server,然后再通过yarn-daemon.sh start resourcemanager,之后发现应用恢复之前的状态然后继续正常运行了。

17/04/08 16:20:09 INFO Client: Retrying connect to server: localhost/127.0.0.1:8032. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
17/04/08 16:20:10 INFO Client: Retrying connect to server: localhost/127.0.0.1:8032. Already tried 1 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)

在日志中,也能发现相关的重新同步的信息,但是任务的运行却没有被中断。

17/04/08 21:53:58 INFO TaskSetManager: Finished task 1.0 in stage 0.0 (TID 1) in 6334 ms on 192.168.31.65 (1/30)
17/04/08 21:53:58 INFO TaskSetManager: Finished task 0.0 in stage 0.0 (TID 0) in 6362 ms on 192.168.31.65 (2/30)
17/04/08 21:54:00 WARN AMRMClientImpl: ApplicationMaster is out of sync with ResourceManager, hence resyncing.
17/04/08 21:54:00 INFO TaskSetManager: Starting task 4.0 in stage 0.0 (TID 4, 192.168.31.65, partition 4,NODE_LOCAL, 2156 bytes)
17/04/08 21:54:00 INFO TaskSetManager: Finished task 3.0 in stage 0.0 (TID 3) in 2460 ms on 192.168.31.65 (3/30)

最后,如果启动恢复ResourceManager状态信息的机制之后,有两点需要注意:

ContainerId的格式会发生改变,因此就需要spark-assembly-1.6.2-hadoopx.x.x.jar中对应的Hadoop版本要能识别这种新的ContainerId,否则就会出现下面的异常。因为我开始在尝试的时候使用的是spark-assembly-1.6.2-hadoop2.4.0.jar,当ResourceManager重启之后,ContainerId使用了新的格式所以无法被之前版本的读取。

# 之前  container_集群时间戳_应用编号_尝试编号_容器编号
container_1491640108912_0001_01_000001
# 之后 container_e{RM重启次数}_集群时间戳_应用编号_尝试编号_容器编号
container_e01_1491640108912_0001_01_000001
java.lang.IllegalArgumentException: Invalid ContainerId: container_e01_1491640108912_0001_01_000001
...
Caused by: java.lang.NumberFormatException: For input string: "e01"

启动恢复ResourceManager状态信息的机制之后,如果借助Zookeeper存储状态信息,则首先需要启动Zookeeper。因为在ResourceManager启动时会尝试建立连接,如果Zookeeper没有启动则会导致ResourceManager启动失败。

参考

> ResourceManager restart > Nodemanager restart

声明: 本文采用 BY-NC-SA 授权。转载请注明转自: Allen写字的地方