hdfs下载数据源码分析之FileSystem.get(conf)浅析

以下代码都是根据在看hadoop视频的时候所用的代码,以下分析是结合视频讲解和我看视频的理解所写的文章。如有侵权请与我联系~

一.通过跟踪这段源码来探究hdfs的下载数据的源码分析。

其中包括程序中怎么通过读取conf来获得fs实例,然后fs实例怎么通过rpc机制来从namenode上拿到元数据信息,以及怎么通过rpc机制从datanode上拿到数据的。

跟踪代码如下:

hdfs下载数据源码分析之FileSystem.get(conf)浅析

跟踪进入FileSystem

hdfs下载数据源码分析之FileSystem.get(conf)浅析

通过getDefaultUri(conf)获得前面代码中设置的主机的uri地址,然后再调用重载的get方法。

以下是重载的get方法内容:

hdfs下载数据源码分析之FileSystem.get(conf)浅析

①getScheme() scheme的值是hdfs,getAuthority是获得namenode的主机名和端口号。

如果scheme==null 以及authority==null 就返回default fs也就是本地文件系统。

②然后拼接disableCacheName,将scheme拼接进去,拼接为fs.hdfs.impl.disable.cache。然后从conf里面区get该参数值,如果有值就返回,如果没值就返回false。该参数的意思是禁用缓存,禁用缓存为false就意味着要用缓存,然后走到下面的程序。CACHE.get(uri,conf).

到这里,filesystem的get方法什么也没做,搞了一堆判断。然后返回的CACHE.get(uri,conf).

我们下面看一下CACHE.get干了什么。

③CACHE是filesystem的内部类

hdfs下载数据源码分析之FileSystem.get(conf)浅析

获得了key(uri和用户名串联起来)

hdfs下载数据源码分析之FileSystem.get(conf)浅析

这里的get也没拿到实际的文件对象,返回了getInternal(uri,conf,key)。

下面是getInternal的方法

hdfs下载数据源码分析之FileSystem.get(conf)浅析

一开始map是空的,然后可能这次处理完之后,就可以把文件系统对象暂时存进去(不同的用户访问集群的时候,都可以把他的文件系统实例放进去,对于一个具体的用户来说,你永远拿到的是同一个对象,对于每一个用户来说相当于单例模式。),做一个缓存作用,万一后面还有下载文件之类的操作,就可以直接从map里面取了。

Fs=null后,就create一个fs对象。具体代码:fs=createFileSystem(uri,conf).

④进入createFileSystem方法。

hdfs下载数据源码分析之FileSystem.get(conf)浅析

首先去拿一个class的文件,根据uri.getScheme和conf来得到这个class,然后进行反射得到fs实例对象。

下面是getFileSystemClass代码:

hdfs下载数据源码分析之FileSystem.get(conf)浅析

此时scheme的值是hdfs,然后conf.getClass(“fs.hdfs.impl”)去获得class,如果conf里面没有这个配置,那么就返回null。

hdfs下载数据源码分析之FileSystem.get(conf)浅析

拿到了就返回clazz。

hdfs下载数据源码分析之FileSystem.get(conf)浅析

拿到了clazz,然后就通过ReflectionUtils反射出fs。Fs里面有个成员DFS,然后通过反射拿到的成员都是空的。

然后进行初始化操作,fs.initialize(uri,Conf)

调用的是filesystem的实现类distributedFileSystem的initialize方法

hdfs下载数据源码分析之FileSystem.get(conf)浅析

这里面分别是对成员赋值。

Dfs是客户端,到目前为止,fs持有dfs对象,但是我们目的是要看到一个rpc的对象,所以这个dfs对象里面应该是持有一个rpc客户端对象。

下面看看new DFSClient()构造方法。

hdfs下载数据源码分析之FileSystem.get(conf)浅析

然后调用一个四个参数的构造函数

hdfs下载数据源码分析之FileSystem.get(conf)浅析

然后看看这个DFSClient中的成员对象:

hdfs下载数据源码分析之FileSystem.get(conf)浅析

有一个namenode的ClientProtocol,这个成员就是客户端和服务端需要共同实现的动态代理对象,它这个是调用真实的namenode的业务方法,所以直接取名为namenode。

在代码中进行一系列赋值和判断之后,主要代码如下:

hdfs下载数据源码分析之FileSystem.get(conf)浅析

然后通过动态代理和反射技术获得proxyinfo对象

hdfs下载数据源码分析之FileSystem.get(conf)浅析

这个failoverProxyProviderClass是针对ha机制的,如果配置了就会走else部分程序,如果没有就return 一个非ha的通信代理对象。然后我们看看createNonHAProxy方法里面干了什么。

hdfs下载数据源码分析之FileSystem.get(conf)浅析

我们这里是客户端,所以和第一个条件匹配,返回的是客户端和namenode通信的proxy,nnAddr就是namenode的ip地址,withRetries是可重试的机制设定(若第一次失败,则重来)。

hdfs下载数据源码分析之FileSystem.get(conf)浅析

 通过RPC.getProtocolProxy获得proxy,最后封装一下返回。

然后一直返回,通过initialize方法的返回值赋值给distributedfilesystem的dfs成员

hdfs下载数据源码分析之FileSystem.get(conf)浅析

最后到工作代码里面来

 hdfs下载数据源码分析之FileSystem.get(conf)浅析

然后fs的open方法首先用namenode这个proxy去调查元数据的方法,查这个数据在哪些block上,这些block在哪个datanode上面。然后再创建一个和datanode通信的代理,然后开始传输数据。

具体open方法会做哪些操作,以及其中是什么样的原理,我们在下一章进行分析。