• HDFS源码解析---NetworkTopology


            NetworkTopology 是common 包下的一个类,用来描述hadoop 集群的节点网络拓扑。在HDFS 中,这个类会在选DN 的场景下被使用。NetworkTopology将整个集群中的DN存储成了一个树状网络拓扑图, 表示一个具有树状网络拓扑结构的计算机集群, 一个集群可能由多个数据中心Data Center组成, 在这些数据中心分布着为计算需求而设置的很多计算机的机架Rack. InnerNode内部类, 表示数据中心/机架的转换器/或路由

            通常来说,一个DN 的拓扑一般是这样的结构 /region/az/idc/room/tor/rack/x,region 通常表示一个地区,az 是逻辑机房,包含多个idc,在idc 内部,通常包含多个房间,每个房间有不同的机柜,一个机柜包含很多机架,而DN (可以抽象为物理机)就放置在机架上。

            Node 接口定义了在网络拓扑中的每一个节点。每一个Node 在网络拓扑中应该有一个名称及其位置(使用类似文件路径的方式来定义), 例如一个Datanode名称为hostname:port,  并且该Datanode在数据中心dog里的orange机架上, 则这个Datanode在网络拓扑中的位置(网络地址)为/dog/orange.  

            NodeBase 实现了Node接口, 是一个最基本的结点的实现. 该类定义的属性都是与一个结点的基本属性信息相关的。假设DN节点的路径path=/a/b/c, 则节点名称name=c, 节点路径location=/a/b.  节点的 path 不需要定义, 由 location/name组成。按照NodeBase的实现, 子节点的location=父节点的path。

            下面来看InnerNode.getLoc()

            假设传入的loc=/a/b/c 表示在region=a,az=b,idc=c,这个方法需要从/a/b/c 这个idc 内选一个节点,当然,这个Node 同样是个树状结构。首先 /a/b/c normalize 后变成a/b/c

    1. /** Given a string representation of a node, return its reference
    2. *
    3. * @param loc
    4. * a path-like string representation of a node
    5. * @return a reference to the node; null if the node is not in the tree
    6. */
    7. public Node getNode(String loc) {
    8. netlock.readLock().lock();
    9. try {
    10. loc = NodeBase.normalize(loc);
    11. if (!NodeBase.ROOT.equals(loc))
    12. loc = loc.substring(1);
    13. return clusterMap.getLoc(loc);
    14. } finally {
    15. netlock.readLock().unlock();
    16. }
    17. }
    1. /** Given a node's string representation, return a reference to the node 参数loc说明了不会传递dn节点名称进来 */
    2. private Node getLoc(String loc) {
    3. if (loc == null || loc.length() == 0) return this;
    4. String[] path = loc.split(PATH_SEPARATOR_STR, 2); // 如果loc=r1/r2, path=[r1, r2]; 如果loc=r1/r2/r3, path=[r1, r2/r3]
    5. Node childnode = null;
    6. for(int i=0; i
    7. if (children.get(i).getName().equals(path[0])) {
    8. childnode = children.get(i);
    9. }
    10. }
    11. if (childnode == null) return null; // non-existing node
    12. if (path.length == 1) return childnode;
    13. if (childnode instanceof InnerNode) {
    14. return ((InnerNode)childnode).getLoc(path[1]); // 递归调用
    15. } else {
    16. return null;
    17. }
    18. }

            第一次 path[0]=region=a 找到/ 下所有的子节点(假设只有/a)匹配上之后,childnode = /a,然后递归 /a .getLoc(b/d)
    第二次 path[0]=az=b 找到/a 下所有子节点(假设只有/a/b)匹配上之后,childnode = /a/b 然后递归 /a/b. getLoc(d)
    第三次 path[0]=idc=d 找到/a/b 下所有子节点(假设只有/a/b/d)匹配上之后,childnode = /a/b/d 此时path 长度=1,返回 childnode。

            这个返回值最后会作为chooseRandom 的入参,在这个节点下的所有节点中选一个DN 出来。

  • 相关阅读:
    windows的arp响应
    人类历史上第一个人工神经元模型为mp模型有何不提出
    leetcode 35 python
    MyBatis指定查询类容、多表查询
    LFS学习系列2 — 总览
    多线程的一些基本理念!
    Redis:19-Redis6新特性
    【自留地】前端 - uniapp - Vue - React - Flutter
    红队打靶:ConnectTheDots打靶思路详解(vulnhub)
    ODrive移植keil(七)—— 插值算法和偏置校准
  • 原文地址:https://blog.csdn.net/ssjdoudou/article/details/126147581