第七章:小朱笔记hadoop之源码分析-hdfs分析
第四节:namenode分析
4.5 namenode心跳检测分析HeartbeatMonitor
DataNode节点在注册时候就开始定期向NameNode节点发送心跳包,以此来告知 NameNode节点自己当前还是可用的,同时从NameNode节点那里得到对自己的控制命令并执行。然而,当一个 DataNode节点没有按时向NameNode节点发送心跳包时,NameNode就会判定这个数据节点已经不可用了,并清除与之相关的数据信息(比如 在改数据节点上的数据块信息)。自然NameNode也再不会把该数据节点分配给客户端使用了。 FSNamesystem$HeartbeatMonitor后台工作线程,用于定期的检查已经接受到的心跳消息,确定哪些 DataNode 已经失效,然后将失效的 DataNode 从系统中移除。 Hadoop 中的心跳消息由 DataNode 发起,NameNode 中进行处理,最终由 HeartbeatMonitor 进行维护。
// heartbeatRecheckInterval is how often namenode checks for expired datanodes
private long heartbeatRecheckInterval;
// heartbeatExpireInterval is how long namenode waits for datanode to report
// heartbeat
private long heartbeatExpireInterval;
......
this.heartbeatRecheckInterval = conf.getInt("heartbeat.recheck.interval", 5 * 60 * 1000); // 5 minutes
this.heartbeatExpireInterval = 2 * heartbeatRecheckInterval +10 * heartbeatInterval;
heartbeatExpireInterval的值等于2个检查周期+10个心跳周期
HeartbeatMonitor 默认每隔5s运行一次,主要有两个工作:
(1)heartbeatCheck
(a)检测datanode是否正常运行
(b)默认每隔5分钟执行一次,可以通过heartbeat.recheck.interval进行配置
(c)遍历heartbeats中保存的datanode列表,判断datanode是否已经超时。超时时间根据heartbeatExpireInterval进行判断,若是超时,则将它从datanodeMap从清除。
(2)updateAccessKey
(a)调用BlockTokenSecretManager.updateKeys,更新currentKey
/**
* Periodically calls heartbeatCheck() and updateAccessKey()
*
* 周期性地调用FSNamesystem类定义的heartbeatCheck方法,来监视Datanode结点发送的心跳状态信息,并做出处理
*/
class HeartbeatMonitor implements Runnable {
private long lastHeartbeatCheck;
private long lastAccessKeyUpdate;
/**
*/
public void run() {
while (fsRunning) {
try {
long now = now();
if (lastHeartbeatCheck + heartbeatRecheckInterval < now) {
heartbeatCheck();
lastHeartbeatCheck = now;
}
if (isAccessTokenEnabled && (lastAccessKeyUpdate + accessKeyUpdateInterval < now)) {
updateAccessKey();
lastAccessKeyUpdate = now;
}
} catch (Exception e) {
FSNamesystem.LOG.error(StringUtils.stringifyException(e));
}
try {
Thread.sleep(5000); // 5 seconds
} catch (InterruptedException ie) {
}
}
}
}
判断dadanode死亡逻辑:NameNode节点是根据数据节点上一次发送的心跳包时间和现在的时间差是否超出heartbeatExpireInterval来判断它是否已dead。
private boolean isDatanodeDead(DatanodeDescriptor node) {
return (node.getLastUpdate() <
(now() - heartbeatExpireInterval));
}