在前面的一篇文章中,我分析了NameNode用来保存DataNode节点的一种数据结构——Host2NodesMap类,它被用来存储主机与DataNode节点之间的映射,同时NameNode用这个数据结构来计算整个集群的负载情况,在本文,我将介绍另一种DataNode节点的存储结构——NetworkTopology。NetworkTopology类将整个集群中的DataNode节点存储成了一个树状网络拓扑图,当然,在NameNode节点把一个DataNode节点交给NetworkTopology类保存之前,它已经将这个DataNode节点坐在的主机ip解析成了一个/*/*/*/*的形式,这样的话,NetworkTopology就更好处理了。
先来看看与NetworkTopology类相关联的类图,以便能更好地了解它是如何来表示整个集群中DataNode节点位置的。
Node接口表示网络拓扑图中节点的抽象,一个Node的实例可能表示的是一个DataNode节点,也可能是集群中的路由器或者是机架,而InnerNode的实例表示的可能是一个路由器,也可能是机架,在中是这样判断是不是机架的:
boolean isRack() {
if (children.isEmpty()) {
return true;
}
Node firstChild = children.get(0);
if (firstChild instanceof InnerNode) {
return false;
}
return true;
}
Node接口的基本实现是NodeBase,用来表示一个节点实体,并且顶多用来表示HDFS集群中的DataNode节点,它的四个属性含义是:
protected String name; //该结点的名称(host:port)protected String location; //该结点的网络位置
protected int level; //该结点在网络拓扑中的层次
protected Node parent; //该结点的父结点
集群中的一个路由器节点可以包含多个路由器节点,也可以包含多个机架节点,一个机架节点可以包含多个DataNode节点,这就是NameNode通过NetworkTopology来管存储群中所有节点的一种方式,那么,它为何要这样来存储呢?实际上,NameNode通过这种树状网络拓扑结构来表示集群中DataNode节点在物理位置上的关系,以方便任何两个DataNode节点之间距离的计算,同时也为NameNode评估集群的负载情况提供计算依据,例如,属于同一个机架的DataNode节点它们在物理上是非常近的,可能就在一个局域网内,同时NamNode也可以计算这个局域网当前的网络带宽的占用情况(这对NameNode节点为一个文件的block副本选取那些存储节点以提高性能是非常重要的)。