Chinaunix首页 | 论坛 | 博客
  • 博客访问: 14826
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 100
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-08 14:16
文章分类
文章存档

2015年(9)

我的朋友

分类: HADOOP

2015-05-12 17:18:46


万事俱备,我们可以来分析NameNode 上的流程啦。
 

首先我们来看NameNode 上实现的ClientProtocol,客户端通过这个接口,可以对目录树进行操作,打开/关闭文件等。
getBlockLocations 用于确定文件内容的位置,它的输入参数为:文件名,偏移量,长度,返回值是一个LocatedBlocks 对象
(如下图),它携带的信息很多,大部分字段我们以前都讨论过。
 

getBlockLocations 直接调用NameSystem 的同名方法。NameSystem 中这样的方法首先会检查权限和对参数进行检查(如偏移量
和长度要大于0),然后再调用实际的方法。找LocatedBlocks 先找src 对应的INode,然后通过INode 的getBlocks 方法,可
以拿到该节点的Block 列表,如果返回为空,表明该INode 不是文件,返回null;如果Block 列表长度为0,以空的Block 数
组构造返回的LocatedBlocks。
如果Block 数组不为空,则通过请求的偏移量和长度,就可以把这个区间涉及的Block 找出来,对于每一个block,执行:
通过BlocksMap 我们可以找到它存在于几个DataNode 上(BlocksMap.numNodes 方法);
计算包含该数据块但数据块是坏的DataNode 的数目(通过NameSystem.countNodes 方法,间接访问CorruptReplicasMap
中的信息);
计算坏数据块的数目(CorruptReplicasMap.numCorruptReplicas 方法,应该和上面的数相等);
通过上面的计算,我们得到现在还OK 的数据块数目;
从BlocksMap 中找出所有OK 的数据块对应的DatanodeDescriptor(DatanodeInfo 的父类);
创建对应的LocatedBlock。
收集到每个数据块的LocatedBlock 信息后,很自然就能构造LocatedBlocks 对象。getBlockLocations 其实只是一个读的方法,
请求到了NameNode 以后只需要查表就行了。
create 方法,该方法用于在目录树上创建文件(创建目录使用mkdir),需要的参数比较多,包括文件名,权限,客户端名,
是否覆盖已存在文件,副本数和块大小。NameNode 的create 调用NameSystem 的startFile 方法(startFile 需要的参数
clientMachine 从线程局部变量获取)。
startFile 方法先调用startFileInternal 完成操作,然后调用logSync,等待日志写完后才返回。
startFileInternal 不但服务于startFile,也被appendFile 调用(通过参数append 区分)。方法的最开始是一堆检查,包括:
安全模式,文件名src 是否正确,权限,租约,replication 参数,overwrite 参数(对append 操作是判断src 指向是否存在
并且是文件)。租约检查很简单,如果通过FSDirectory.getFileINode(src)得到的文件是出于构造状态,表明有客户正在操
作该文件,这时会抛出异常AlreadyBeingCreatedException。
如果对于创建操作,会通过FSDirectory 的addFile 往目录树上添加一个文件并在租约管理器里添加一条记录。
对于append 操作,执行的是构造一个新的INodeFileUnderConstruction 并替换原有的节点,然后在租约管理器里添加一条记
录。
总的来说,最简单的create 流程就是在目录树上创建一个INodeFileUnderConstruction 对象并往租约管理器里添加一条记录。
我们顺便分析一下append 吧,它的返回值是LocatedBlock,比起getBlockLocations,它只需要返回数组的一项。appendFile
是NameSystem 的实现方法,它首先调用上面讨论的startFileInternal 方法(已经在租约管理器里添加了一条记录)然后写日
志。然后寻找对应文件INodeFile 中记录的最后一个block,并通过BlocksMap.getStoredBlock()方法得到BlockInfo,然后
再从BlocksMap 中获得所有的DatanodeDescriptor,就可以构造LocatedBlock 了。需要注意的,如果该Block 在需要被复制
的集合(UnderReplicatedBlocks)中,移除它。
如果文件刚被创建或者是最后一个数据块已经写满,那么append 会返回null,这是客户端需要使用addBlock,为文件添加数
据块。
更多精彩内容请关注:
关注超人学院微信:BJ-CRXY
阅读(599) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~