整个namenode之间的ha保证是通过ZKFC这个组件来完成的。
- 该组件核心是以下三个类
ActiveStandbyElector : 负责跟ZK之间的心跳检查 - HealthMonitor : 两个namenode之间的心跳检查,主要是看对方的本地磁盘是否足够。若是磁盘空间不足,或者对方响应超时,那么就会触发ha切换
- ZKFCRpcServer : 接受对方的请求 cedeActive / gracefulFailover 也是比较鸡肋的Server
HealthMonitor :
org.apache.hadoop.ha.HealthMonitor.MonitorDaemon#run 一个while循环的检查doHealthChecks
在doHealthChecks 方法中抛出异常的话,那么进入 enterState(State.SERVICE_NOT_RESPONDING); 这个时候会触发HealthMonitor自身在初始化时候添加的callback=HealthCallbacks .
HealthCallbacks 中通过方法 recheckElectability 检查最后的状态
case SERVICE_NOT_RESPONDING: LOG.info("Quitting master election for " + localTarget + " and marking that fencing is necessary"); elector.quitElection(true); serviceState = HAServiceState.INITIALIZING; break;
若是SERVICE_NOT_RESPONDING,自己就推出 org.apache.hadoop.ha.ActiveStandbyElector#quitElection 。这个方法主要是断开跟ZK之间的连接
public synchronized void terminateConnection() { if (zkClient == null) { return; } if (LOG.isDebugEnabled()) { LOG.debug("Terminating ZK connection for " + this); } ZooKeeper tempZk = zkClient; zkClient = null; watcher = null; try { tempZk.close(); } catch(InterruptedException e) { LOG.warn(e); } zkConnectionState = ConnectionState.TERMINATED; wantToBeInElection = false; }
这个时候ActiveStandbyElector要发现作用了。
通过org.apache.hadoop.ha.ActiveStandbyElector.WatcherWithClientRef watch了zk的路径
具体是通过org.apache.hadoop.ha.ActiveStandbyElector#processWatchEvent 中的事件处理
case NodeDeleted: if (state == State.ACTIVE) { enterNeutralMode(); } joinElectionInternal(); break;
检测到路径被删除了,那么就自己去抢路径,在 joinElectionInternal内部的createLockNodeAsync方法中
private void createLockNodeAsync() { zkClient.create(zkLockFilePath, appData, zkAcl, CreateMode.EPHEMERAL, this, zkClient); }
中的第五个参数 this传递进去了,这个this就是ActiveStandbyElector 实现了StatCallback, StringCallback接口,在抢个路径后会触发以下两个方法中的一个
org.apache.hadoop.ha.ActiveStandbyElector#processResult(int, java.lang.String, java.lang.Object, java.lang.String)
org.apache.hadoop.ha.ActiveStandbyElector#processResult(int, java.lang.String, java.lang.Object, org.apache.zookeeper.data.Stat)
进入了 becomeActive
Code code = Code.get(rc); if (isSuccess(code)) { // the following owner check completes verification in case the lock znode // creation was retried if (stat.getEphemeralOwner() == zkClient.getSessionId()) { // we own the lock znode. so we are the leader if (!becomeActive()) { reJoinElectionAfterFailureToBecomeActive(); } } else { // we dont own the lock znode. so we are a standby. becomeStandby(); } // the watch set by us will notify about changes return; }
完成了最后的namenode ha切换
BTW:如果这段逻辑用 curator-framework来写的话会简单很多。
0 条评论。