HDFS DatanodeProtocol——register

每当Datanode启动的时候,Datanode需要向Namenode注册自己。对于Datanode来说,注册的目的有两个:1)报告Datanode当前正在提供的存储(storage)2)从Namenode获取registrationID用来标识当前的Datanode。对于Namenode来说:Namenode通过注册来区分Datanode是不是提供一个新的storage(这个新的storage Namenode是不知道的,storage是通过Namenode分配唯一的storageID来进行区分的),并向Namenode报告新的block;还是这个Datanode是原来storage的替代,该storage原来被该Datanode或其他Datanode提供(通过host:port进行区别)。最后,Namenode将其namespaceID返回给Datanode,作为DatanoderesistrationIDNamenodeDatanode的每一次交互都要检查namespaceID是否相符。

下面我们讨论一下如何来完成Datanode的注册。从上面的分析我们知道Datanode可能两种状态,一种是Datanode是全新的,里面没有storage;另外一种情况是Datanode已经保存了某个已有的storage。如果是全新的,那么处理的过程可能比较简单,将该Datanode保存到host2DataNodeMap中;给Datanode分配storageID,并将该storageID存放到datanodeMap中。如果Datanode保存了一个已有的storageID(我们称之为已有新服务storage),那么首先判断该Datanode原来是不是已经注册过并且保存了一个storage(我们称之为已有应删除storage),如果保存了就将该Datanode上原来的已有应删除storage删除,删除后再来服务已有新服务storage。然后修改已有新服务storageDatanode,使之与当前Datanode一致。最后将该Datanode存放到host2DataNodeMap中。

我们看一下程序的源代码:

public synchronized void registerDatanode(DatanodeRegistration nodeReg)

throws IOException {

//获取DatanodeIP

String dnAddress = Server.getRemoteAddress();

if (dnAddress == null) {

// Mostly called inside an RPC.

// But if not, use address passed by the data-node.

dnAddress = nodeReg.getHost();

}

// check if the datanode is allowed to be connect to the namenode

//检查该Datanode是否允许连接到本Namenode,主要是检查该Datanode是否包含在

//slaves配置文件当中,并且不包含在exclude列表当中

if (!verifyNodeRegistration(nodeReg, dnAddress)) {

throw new DisallowedDatanodeException(nodeReg);

}

//获取DatanodehostName

String hostName = nodeReg.getHost();

// update the datanode's name with ip:port

DatanodeID dnReg = new DatanodeID(dnAddress + ":" + nodeReg.getPort(),

nodeReg.getStorageID(), nodeReg.getInfoPort(),

nodeReg.getIpcPort());

nodeReg.updateRegInfo(dnReg);

nodeReg.exportedKeys = getBlockKeys();

NameNode.stateChangeLog.info("BLOCK* NameSystem.registerDatanode: "

"node registration from " + nodeReg.getName() + " storage "

+ nodeReg.getStorageID());

/*datanodeMap{storageID->DatanodeDescriptor}

 * 如果nodeReg包含了一个storage,那么nodeReg.getStorageID()

 * 将不为空,那么nodeS就是该storage对应的Datanode

 * (注意该Datanode不一定是现在正在注册的Datanode)。

 * 需要将该storage对应的Datanode更新到现在正在注册的Datanode

 */

DatanodeDescriptor nodeS = datanodeMap.get(nodeReg.getStorageID());

/*

 * host2DataNodeMap中获取该hostName所对应的DatanodeDescriptor

 */

DatanodeDescriptor nodeN = host2DataNodeMap.getDatanodeByName(nodeReg

.getName());

/*

 * nodeN!=null表明正在注册的Datanode原来已经注册过。

 * 既然已经注册过,那么nodeN必然有了自己

 * storage。当时nodeS!=nodeN,表明nodeN正在服务一个新

 * storage。所以必须将其原来的storage删除

 */

if (nodeN != null && nodeN != nodeS) {

NameNode.LOG.info("BLOCK* NameSystem.registerDatanode: "

"node from name: " + nodeN.getName());

// nodeN previously served a different data storage,

// which is not served by anybody anymore.

removeDatanode(nodeN);

// physically remove node from datanodeMap

wipeDatanode(nodeN);

nodeN = null;

}

if (nodeS != null) {

if (nodeN == nodeS) {

// The same datanode has been just restarted to serve the same

// data

// storage. We do not need to remove old data blocks, the delta

// will

// be calculated on the next block report from the datanode

NameNode.stateChangeLog

.debug("BLOCK* NameSystem.registerDatanode: "

"node restarted.");

else {

// nodeS is found

/*

 * The registering datanode is a replacement node for the

 * existing data storage, which from now on will be served by a

 * new node. If this message repeats, both nodes might have same

 * storageID by (insanely rare) random chance. User needs to

 * restart one of the nodes with its data cleared (or user can

 * just remove the StorageID value in "VERSION" file under the

 * data directory of the datanode, but this is might not work if

 * VERSION file format has changed

 */

NameNode.stateChangeLog

.info("BLOCK* NameSystem.registerDatanode: " + "node "

+ nodeS.getName() + " is replaced by "

+ nodeReg.getName()

" with the same storageID "

+ nodeReg.getStorageID());

}

// update cluster map

clusterMap.remove(nodeS);

/*

 * 在这种情况下nodeS!=null,表明正在注册的Datanode已经

 * 正在服务一个storage。如果nodeN==nodeS,表明该storage

 * 原来就保存在该Datanode上,只是重启了该Datanode

 * 如果nodeN!=nodeS,表明该storage原来保存在其他Datanode上,

 * 现在保存到了该Datanode。首先,从clusterMap中移除nodeS

 * 然后更新nodeSDatanode,并在clusterMap中重新添加nodeS

 */

nodeS.updateRegInfo(nodeReg);

nodeS.setHostName(hostName);

// resolve network location

resolveNetworkLocation(nodeS);

clusterMap.add(nodeS);

// also treat the registration message as a heartbeat

synchronized (heartbeats) {

if (!heartbeats.contains(nodeS)) {

heartbeats.add(nodeS);

// update its timestamp

nodeS.updateHeartbeat(0L, 0L, 0L, 0);

nodeS.isAlive = true;

}

}

return;

}

// this is a new datanode serving a new data storage

/*

 * 如果storageID为空,表明该Datanod是一个全新的Datanode

 * 需要分配一个storageID,并将该Datanode添加到datanodeMap

 * host2DataNodeMap

 */

if (nodeReg.getStorageID().equals("")) {

// this data storage has never been registered

// it is either empty or was created by pre-storageID version of DFS

nodeReg.storageID = newStorageID();

NameNode.stateChangeLog

.debug("BLOCK* NameSystem.registerDatanode: "

"new storageID " + nodeReg.getStorageID()

" assigned.");

}

// register new datanode

DatanodeDescriptor nodeDescr = new DatanodeDescriptor(nodeReg,

NetworkTopology.DEFAULT_RACK, hostName);

resolveNetworkLocation(nodeDescr);

unprotectedAddDatanode(nodeDescr);

clusterMap.add(nodeDescr);

// also treat the registration message as a heartbeat

synchronized (heartbeats) {

heartbeats.add(nodeDescr);

nodeDescr.isAlive = true;

// no need to update its timestamp

// because its is done when the descriptor is created

}

return;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值