文章链接1:下载hdfs中的文件(原始写法)
文章链接2:跟踪分析数据源码1
1.在以下代码处加断点
FSDataInputStream in = fs.open(src);
2.
(1)此时进入open到FileSystem.class中 的open(即父类open),此函数中并没有做什么实质性的工作。此时再进入open是一个抽象函数
(2)所以进入其实现方法Open Implementation在跳出的类列表中选择DistributedFileSystem
(3)①statistics就是一些简单的统计记录
②absF是将相对路径变为绝对路径的绝对路径
③最后这个.resolve返回的就是这个流
④进入return dfs.createWrappedInputStream(dfsis);此处可以看出最后是将DFSInputStream封装成了一个HdfsDataInputStream
⑤再看其类结构HdfsDataInputStream是FSDataInputStream的子类
(4)dfs就是fs的成员,用fs打开文件实质就是用dfs打开文件,再跟踪下去实质就是用NameNode去通信真实的NameNode获取块的信息来打开文件
3.进入此处的open,就进到了DFSClient.class
4.src是要下载的文件路径,verifychecksum是是否验证校验和,TRUE就是验证,locatedblocks是块位置信息
5.进入 openInternal最后返回new的DFSInputStream,进入DFSInputStream.class
6.此处dfsClient其实就是fs中的dfs
7.进入openInfo,,,fetchLocatedBlocksAndGetLastBlockLength找到块位置和得到最后一个块的长度(因为只有最后一个块有可能是不满的),进入fetchLocatedBlocksAndGetLastBlockLength,再进入getLocatedBlocks,再进入callGetBlockLocations
可以看到是namenode调用getBlockLocations,此处namenode代理对象调用的是真实的namenodesever上的方法,它们共同实现接口
8.上面不再深入分析,回到DFSInputStream.class的fetchLocatedBlocksAndGetLastBlockLength中,,LocatedBlocks newInfo = locatedBlocks;的newInfo得到的信息如下:
LocatedBlocks{;
fileLength=195094741;
underConstruction=false;
blocks=[
LocatedBlock{BP-1050190351-192.168.184.128-1570722230769:blk_1073741873_1049; getBlockSize()=134217728; corrupt=false; offset=0; locs=[DatanodeInfoWithStorage[192.168.184.128:9866,DS-3f3ddd05-55f4-4786-b49b-9e8b09446d1a,DISK]]},
LocatedBlock{BP-1050190351-192.168.184.128-1570722230769:blk_1073741874_1050; getBlockSize()=60877013; corrupt=false; offset=134217728; locs=[DatanodeInfoWithStorage[192.168.184.128:9866,DS-3f3ddd05-55f4-4786-b49b-9e8b09446d1a,DISK]]}
];
lastLocatedBlock=LocatedBlock{BP-1050190351-192.168.184.128-1570722230769:blk_1073741874_1050; getBlockSize()=60877013; corrupt=false; offset=134217728; locs=[DatanodeInfoWithStorage[192.168.184.128:9866,DS-3f3ddd05-55f4-4786-b49b-9e8b09446d1a,DISK]]}; isLastBlockComplete=true; ecPolicy=null}
注:corrupt=false表示有没有损坏,offset=0表示起始的偏移量,192.168.184.128:9866表示在192.168.184.128这个DataNode上通过9866端口去取,isLastBlockComplete=true表示是否完成即如果文件一边在上传一边在下载是不允许被下载的因为还没有上传完成,所以需要判断。
进入路径/home/centosdvd/app/hadoop-3.2.1/data/dfs/data/current/BP-1050190351-192.168.184.128-1570722230769/current/finalized/subdir0/subdir0下有分块信息,可以和以上newInfo信息对照
9.此时locatedBlocks基本已经得到,查看输入流的成员中blockReader也很重要,此处不再叙述,可根据以上流程自己跟踪分析一下。
10.一些重要代码