Hadoop-组件-HDFS-理论笔记-HDFS 架构设计-DataNode 架构-逻辑层设计-BlockPoolManager
一、概述
在 HDFS Federation 部署中,一个 HDFS 集群可以配置多个命名空间,每个 Datanode 都会存储多个块池的数据块。在 Datanode 实现中,定义了 BlockPoolManager 类来管理 Datanode 上的所有块池,Datanode 的其他模块对块池的操作都必须通过 BlockPoolManager 执行,每个 Datanode 都有一个 BlockPoolManager 的实例。
二、架构设计
2.1. 逻辑结构图
BlockPoolManager 逻辑结构图如图所示。
2.1.1. BPOfferService
在 HDFS Federation 部署中,一个 Datanode 会保存多个块池的数据块,所以 BlockPoolManager 会拥有多个 BPOfferService 对象,每个 BPOfferService 对象都封装了对单个块池操作的 API。
2.1.2. BPOfferServiceActor
在 HDFS HA 部署中,每个命名空间会同时拥有两个 Namenode,一个作为活动的 (Active) Namenode,另一个作为热备的 (Standby)Namenode, 每个 BPOfferService 都会包含两个 BPServiceActor 对象,每个 BPServiceActor 对象封装了与该命名空间中单个 Namenode 的操作,包括定时向这个 Namenode 发送心跳(heartbeat)、增量块汇报(blockReceivedAndDeleted)、全量块汇报(blockreport)、缓存块汇报(cacheReport) 以及执行 Namenode 通过心跳/块汇报响应传回的名字节点指令等操作。
三、实现
BlockPoolManager 类负责管理所有的 BPOfferService 实例,对外提供添加、删除、启动、停止、关闭 BPOfferService 类的接口。所有对 BPOfferService 的操作,都必须通过 BlockPoolManager 类提供的方法来执行。同时在 BlockPoolManager 的实现中,使用 BPServiceActor 类负责与一个 Namenode 通信。每 BPServiceActor 的实例都是一个独立运行的线程,这个线程主要实现了以下功能:
- 与 Namenode 进行第一次握手,获取命名空间的信息。
- 向 Namenode 注册当前 Datanode。
- 定期向 Namenode 发送心跳、增量块汇报、全量块汇报以及缓存块汇报。
- 执行 Namenode 传回的名字节点指令。
3.1. 字段
3.2. 初始化 refreshNamenodes()
DataNode.startDataNode() 方法初始化了 BlockPoolManager 对象,然后调用 BlockPoolManager.refreshNamenodes() 方法完成对 BlockPoolManager 的构造。
3.2.1. 构造 toRefresh、 toAdd、 toRemove 三个队列
添加、更新、删除 BPOfferService,方法中的 addrMap 变量保存了配置的命名空间列表,bpByNameserviceId 变量则保存了当前 BlockPoolManager 中己有的命名空间列表。
- 如果命名空间列表中存在,BlockPoolManager 的 Map 中不存在,则将当前的 nameserviceId 添加到 toAdd 队列中。
- 如果命名空间列表中存在,BlockPoolManager 的 Map 中也存在,则将当前的 nameserviceId 添加到 toRefresh 队列中。
- 如果 BlockPoolManager 的 Map 中存在,命名空间列表中不存在,则将当前的 nameserviceId 添加到 toRemove 队列中。
3.2.2. 处理 toAdd 队列
toAdd 队列中保存了需要添加到 BlockPoolManager 中的命名空间,refreshNamenodes() 方法会首先调用 createBPOS() 方法创建 BPOfferService 对象,BPOfferService 的构造方法会对命名空间中定义的每一个 Namenode 构造对应的 BPServiceActor 对象,并将这些新创建的对象放入 BPOfferService 的数据结构中保存。BPOfferService 构造完成后,将会放入 BlockPoolManager.bpByNameserviceId 映射中保存,然后调用 startAll() 方法启动所有的 BPOfferService,BPOfferService 会级联启动所有的 BPServiceActor 的工作线程。
3.2.3. 处理 toRemove 队列
toRemove 队列中保存了要从 BlockPoolManager 中删除的命名空间。对于 toRemove 队列中保存的命名空间,停止它对应的 BPOfferService 的服务,也就是停止 BPOfferService 中所有的 BPServiceActor 线程。当 BPOfferService 的所有 BPServiceActor 线程都停止后,会自动
从 BlockPoolManager.bpByNameserviceId 映射中移除当前的 BPOfferService 对象。
3.2.4. 处理 toRefresh 队列
对于 toRefresh 队列中保存的命名空间,则调用 BPOfferService.refreshNNList() 方法更新该命名空间中的 Namenode 列表。