[HADOOP] 简单了解NameNode的ZKFC机制

博客原文:hackershellnode

以前在准备中级课程PPT,整理了下HA的基本内容,而且感谢松哥为咱们提供了HA不会切的问题,以致于以后恰好出现的NameNode宕机,可以快速解决。算法

NameNode的HA能够我的认为简单分为共享editLog机制和ZKFC对NameNode状态的控制shell

在此以前,我先提几个问题:网络

  • 通常致使NameNode切换的缘由数据结构

  • ZKFC的做用是什么?如何判断一个NN是否健康ssh

  • NameNode HA是如何实现的?ide

  • NameNode由于断电致使不能切换的原理,怎样进行恢复函数

通常致使NameNode切换的缘由ui

随着集群规模的变大和任务量变多,NameNode的压力会愈来愈大,一些默认参数已经不能知足集群的平常需求,除此以外,异常的Job在短期内建立和删除大量文件,引发NN节点频繁更新内存的数据结构从而致使RPC的处理时间变长,CallQueue里面的RpcCall堆积,甚至严重的状况下打满CallQueue,致使NameNode响应变慢,甚至无响应,ZKFC的HealthMonitor监控本身的NN异常时,则会断开与ZooKeeper的连接,从而释放锁,另一个NN上的ZKFC进行抢锁进行Standby到Active状态的切换。这是通常引发的切换的流程。this

固然,若是你是手动去切换这也是能够的,当Active主机出现异常时,有时候则须要在必要的时间内进行切换。

ZKFC的做用是什么?如何判断一个NN是否健康

在正常的状况下,ZKFC的HealthMonitor主要是监控NameNode主机上的磁盘仍是否可用(空间),咱们都知道,NameNode负责维护集群上的元数据信息,当磁盘不可用的时候,NN就该进行切换了。

/**
   * Return true if disk space is available on at least one of the configured
   * redundant volumes, and all of the configured required volumes.
   * 
   * @return True if the configured amount of disk space is available on at
   *         least one redundant volume and all of the required volumes, false
   *         otherwise.
   */
  public boolean hasAvailableDiskSpace() {
    return NameNodeResourcePolicy.areResourcesAvailable(volumes.values(),
        minimumRedundantVolumes);
  }

除了可用状态(SERVICE_HEALTHY)以外,还有SERVICE_UNHEALTHY(磁盘空间不可用),SERVICE_NOT_RESPONDING(其余的一些状况)状态,在这两个状态中,它都认为NN是不健康的。

NameNode HA是如何实现的?

咱们前面说到,ZKFC是如何判断NN是否健康,接下来当NN处于非健康状态时,NameNode是如何进行切换的呢?

zkfc.png

在ZKFailoverController这个类中,实行了两个重要的Callbacks函数,一个叫ElectorCallbacks,另外一个叫HealthCallbacks,顾名思义就是选举和健康检查用的回调函数,其中还有两个重要的组成部分elector(ActiveStandbyElector)healthMonitor(HealthMonitor),整体的就如上图所示。

ElectorCallbacks:

/**
   * Callbacks from elector
   */
  class ElectorCallbacks implements ActiveStandbyElectorCallback {
    @Override
    public void becomeActive() throws ServiceFailedException {
      ZKFailoverController.this.becomeActive();
    }

    @Override
    public void becomeStandby() {
      ZKFailoverController.this.becomeStandby();
    }
...
}

HealthCallbacks:

/**
   * Callbacks from HealthMonitor
   */
  class HealthCallbacks implements HealthMonitor.Callback {
    @Override
    public void enteredState(HealthMonitor.State newState) {
      setLastHealthState(newState);
      recheckElectability();
    }
  }

对于HealthMonitor来讲,在ZKFC进程启动的时候,就已经将HealthCallbacks注册进去了,HealthMonitor都会按期的检查NameNode是否健康,咱们能够经过监控ha.health-monitor.check-interval.ms去设置监控的间隔时间和经过参数ha.health-monitor.rpc-timeout.ms设置timeout时间,当集群变大的时候,须要适当的设置改值,让ZKFC的HealthMonitor没那么“敏感”

ZKFC经过RPC调用监控NN进程,当出现异常时,则进入不一样的处理逻辑,如下是简化的代码:

private void doHealthChecks() throws InterruptedException {
    while (shouldRun) {     
      try {
        status = proxy.getServiceStatus();
        proxy.monitorHealth();
        healthy = true;
      } catch (HealthCheckFailedException e) {
       ...
        enterState(State.SERVICE_UNHEALTHY);
      } catch (Throwable t) {
       ...
        enterState(State.SERVICE_NOT_RESPONDING);
        Thread.sleep(sleepAfterDisconnectMillis);
        return;
      }
      ...
}

回调函数就是这么起做用啦,那么回调函数作了什么呢?总的来讲,若是NN健康(SERVICE_HEALTHY)就加入选举,若是不健康就退出选举(SERVICE_UNHEALTHYSERVICE_NOT_RESPONDING

case SERVICE_UNHEALTHY:
        case SERVICE_NOT_RESPONDING:
          LOG.info("Quitting master election for " + localTarget +
              " and marking that fencing is necessary");
          elector.quitElection(true);
          break;

说到退出选举就关系到elector(ActiveStandbyElector)了,true表明若是NN从Actice变为Standby出现异常是要去fence的,这就是为啥NN会挂掉的缘由之一

如何退出选举?就是close zkClient的连接,让ZooKeeper上面的维持的选举锁消失

void terminateConnection() {
    if (zkClient == null) {
      return;
    }
    LOG.debug("Terminating ZK connection for " + this);
    ZooKeeper tempZk = zkClient;
    ...
    try {
      tempZk.close();
    } catch(InterruptedException e) {
      LOG.warn(e);
    }
   ...
  }

对于ActiveStandbyElector来讲,他有个WatcherWithClientRef类专门用来监听ZooKeeper上的的znode的事件变化,当事件变化时,就会调用ActiveStandbyElector的processWatchEvent的方法

watcher = new WatcherWithClientRef();
ZooKeeper zk = new ZooKeeper(zkHostPort, zkSessionTimeout, watcher);

/**
   * Watcher implementation which keeps a reference around to the
   * original ZK connection, and passes it back along with any
   * events.
   */
  private final class WatcherWithClientRef implements Watcher {
...
    @Override
        public void process(WatchedEvent event) {
          hasReceivedEvent.countDown();
          try {
            hasSetZooKeeper.await(zkSessionTimeout, TimeUnit.MILLISECONDS);
            ActiveStandbyElector.this.processWatchEvent(
                zk, event);
          } catch (Throwable t) {
            fatalError(
                "Failed to process watcher event " + event + ": " +
                StringUtils.stringifyException(t));
          }
        }
...
}

在ActiveStandbyElector的processWatchEvent方法中,处理来自不一样事件的逻辑从新加入选举或者继续监控znode的变化,当另一个ZKFC监控到事件变化得时候,就去抢锁,抢锁实质上就是建立znode的过程,并且建立的是CreateMode.EPHEMERAL类型的,因此,当HealthMonitor监控到NN不健康时,就会断开链接,节点就会消失,watcher就会监控到NodeDeleted事件,进行建立节点。

switch (eventType) {
      case NodeDeleted:
        if (state == State.ACTIVE) {
          enterNeutralMode();
        }
        joinElectionInternal();
        break;
      case NodeDataChanged:
        monitorActiveStatus();
        break;

又由于ActiveStandbyElector实现了StatCallback接口,当节点建立成功时,就会回调processResult方法看是否建立成功,若是建立成功则去检查zkBreadCrumbPath是否存在以前的Active节点,若是存在,则调用RPC让其变为Standby,看可否转变成功,不然则SSH过去fence掉NN进程。,保持Active节点只有一个,而且恢复正常服务

NameNode由于断电致使不能切换的原理,怎样进行恢复

ActiveNN断电,网络异常,负载太高或者机器出现异常没法链接,Standby NN没法转化为Active,使得HA集群没法对外服务,缘由是Active NN节点在断电和不能服务的状况下,zknode上保存着ActiveBreadCrumb, ActiveStandbyElectorLock两个Active NN的信息,ActiveStandbyElectorLock因为Active NN出现异常断开,Standby NN去抢锁的时候就会去检查ActiveBreadCrumb是否有上一次的Active NN节点,若是有,就会就会尝试让Active NN变为Standby NN,本身转化为Active NN,可是因为调用出现异常,因此会采用ssh的方式去Fence以前的Active NN,由于机器始终链接不上,因此没法确保old active NN变为Standby NN,本身也没法变为Active NN,因此仍是保持Standby状态,避免出现脑裂问题。

解决方案是肯定Active关机的状况下从新hdfs zkfc -formatZK就能够了。

总 结

NN GC或者在压力大的状况下能够调整GC算法和增长NameNode节点的线程数,加快NN对请求的处理速度,也能够分离节点的端口dfs.namenode.rpc-address.ns1.nn2dfs.namenode.servicerpc-address.ns1.nn2分离client和datanode节点等服务类型的请求,进行分担压力,也能够适当的调整ZKFC的监控timeout的时间等等

可是遇到异常的job,只能经过别的方式去处理问题了,祷告吧!哈哈

相关文章
相关标签/搜索