[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,只能經過別的方式去處理問題了,禱告吧!哈哈

相關文章
相關標籤/搜索