2.2 线程模型
由上图可以看出,整个系统中有3类线程:
- 主线程:在启动所有服务后开始循环等待
- HealthMonitor线程:定期检查NN服务状态和健康状况,并在服务状态和健康状态发生变化时与ActiveStandbyElector交互完成HA过程
- zk客户端线程:监控zookeeper上结点的状态,发生变化时,回调ZKFailoverController的回调函数,通知ZKFailoverController,做出相应的变化
2.3 RPC代理对象
从上图可以看出,有3类RPC代理对象:
-
proxy1:ZKFC对本节点NN健康检查
超时时间:“ha.health-monitor.rpc-timeout.ms” 默认45s
最大重试次数:“ipc.client.connect.max.retries”,在代码中被set为1,即失败后会重连一次
重连间隔:“ipc.client.connect.retry.interval” 默认1s,在我们集群中设置为10s。
和NN RPC通信地址:根据"dfs.namenode.lifeline.rpc-address.nsId.nnId"。如果没有指定该配置项,则和下面2、3的地址相同。
*注:该配置项用于配置HM健康检查和Datanode上报心跳的地址,由另外的RPC handler而非main RPC handler处理,可应对负载过高,main RPC handler耗尽的场景。
-
proxy2:ZKFC对另一个节点的NN fence
超时时间:“ha.failover-controller.graceful-fence.rpc-timeout.ms” 默认5s
最大重试次数:“ipc.client.connect.max.retries” 在代码中被set为1,即失败后会重连一次
重连间隔:“ipc.client.connect.retry.interval” 默认1s,在我们集群中设置为10s。
和NN RPC通信地址:先根据"dfs.namenode.servicerpc-address.nsId.nnId",没有再根据"dfs.namenode.rpc-address.nsId.nnId",若这些配置项中没有指定端口,则默认端口为8020。在我们的配置中已指定端口为9000。
-
proxy3:ZKFC对本节点的NN转换状态(becomeActive/Standby)
超时时间:“ha.failover-controller.new-active.rpc-timeout.ms” 默认60s
最大重试次数:“ipc.client.connect.max.retries” 在代码中被set为1,即失败后会重连一次
重连间隔:“ipc.client.connect.retry.interval” 默认1s,在我们集群中设置为10s。
和NN RPC通信地址:先根据"dfs.namenode.servicerpc-address.nsId.nnId",没有再根据"dfs.namenode.rpc-address.nsId.nnId",若这些配置项中没有指定端口,则默认端口为8020。在我们的配置中已指定端口为9000。
2.4 正常HA切换流程
下面结合上图梳理启动时的状态切换流程:
-
启动后,两个NN都会进入Standby状态
-
两个ZKFC的HealthMonitor都检测到Namenod健康状态为SERVICE_HEALTHY,健康状态从INITIALIZING变为SERVICE_HEALTHY,状态改变,执行joinElection()方法加入选举。
-
两个ZKFC都会尝试创建锁节点,假设ZKFC1创建成功,ZKFC2创建失败
-
ZKFC2所在节点NN状态维持Standby,在锁节点上注册watcher,监控锁节点状态
-
ZKFC1检测到ActiveBreadCrumb节点不存在,不需要fence另一个NN;创建ActiveBreadCrumb节点;通过proxy3转换本节点NN状态为Active;在锁节点上注册watcher,监控锁节点状态。