Hadoop 2.6.5 FileSystem和Configuration两个对象的探究html
版权声明:本文为yunshuxueyuan原创文章,如需转载,请标明出处。【http://www.cnblogs.com/sxt-zkys/】
QQ技术交流群:299142667node
(结论)缓存
经过尚学堂旗下云数学院大数据周老师的讲解能够获得如下结论:用相同的地址获取的FileSystem对象是同一个; 第一次获取对象后会有相似于缓存的机制, 即便改变了configuration参数, 只要地址没有发生变化, 获取的FileSystem 对象不会改变.服务器
[从bug开始]oop
在测试上传数据到HDFS集群时, 想更改blocksize的大小来测试小文件分块的状况, 使用了以下代码(为了便于阅读, 删去了JUNIT的注解):测试
Configuration conf = null; FileSystem fs = null; //初始化fs对象 conf = new Configuration(true); fs = FileSystem.get(conf); //更改blocksize大小 conf.set("dfs.blocksize", "1048576"); fs = FileSystem.get(conf); //上传文件 Path srcPath = new Path("d:\\testup.txt"); Path dstPath = new Path("/user/root/test03.txt"); fs.copyFromLocalFile(srcPath, dstPath);
从结果来看, 生成的文件大小并无改变:大数据
那咱们从新定义一个FileSystem来尝试一下:spa
因而接着上段代码, 有了以下代码:debug
//初始化fs2对象 Configuration conf2 = new Configuration(true); conf2.set("dfs.blocksize", "1048576"); FileSystem fs2 = FileSystem.get(conf2); //上传文件 Path dstPath2 = new Path("/user/root/test04.txt"); fs2.copyFromLocalFile(srcPath, dstPath2);
然而结果并不乐观:code
此时其余的小伙伴@2元店主 已经完成了测试, 上传文件成功, 而且设置分块大小也没有问题, 他的代码以下:
//初始化fs对象 Path srcPath = new Path("d:\\testup.txt"); Path dstPath = new Path("/user/root/test07.txt"); Configuration confnew = new Configuration(true); confnew.set("dfs.blocksize", "1048576"); FileSystem fsnew = FileSystem.get(confnew); //上传文件 fsnew.copyFromLocalFile(srcPath, dstPath);
对比能够发现, 其中的核心代码并无什么差别, 那么是什么问题引发的blocksize改变不成功呢?
通过尚学堂同班同窗的大力协助, 咱们肯定了差别点, 在个人测试代码中, 先从配置(conf)生成过了一次FileSystem对象, 更改的blocksize后再次生成FileSystem对象. 多是这个过程出现了问题.
若是是这个问题, 那么个人第二次测试的代码也失效根本说不过去, 由于我是全新的对象, 与以前对象并没有关联.
到了这里, 咱们对bug的产生有了一些思路.
[进一步测试]
为了明确具体的问题所在, 有了以下代码:
由于下面的代码长得我都不想仔细读, 因此在这里说一下大概思路:
测试代码两两一组, 每组获取FileSystem对象用的地址是相同的;
第一组读取本地配置文件, 先生成FileSystem对象后更改blocksize配置, 再次生成FileSystem对象
第二组不读取本地配置文件, 地址是node01, 先更改blocksize为1M, 生成FileSystem对象, 改变blocksize为128M, 再次生成FileSystem对象
第三组不读取本地配置文件, 地址是192.168的具体地址, 先更改blocksize为128M, 生成FileSystem对象, 改变blocksize为1M, 再次生成FileSystem对象
最后, 输出全部的FileSystem对象toString方法
//第一组 Configuration confa = new Configuration(true); FileSystem fsa = FileSystem.get(confa); confa.set("dfs.blocksize", "1048576"); fsa = FileSystem.get(confa); System.out.println(fsa.getDefaultBlockSize()); Configuration confb = new Configuration(true); confb.set("dfs.blocksize", "1048576"); FileSystem fsb = FileSystem.get(confb); System.out.println(fsb.getDefaultBlockSize()); //第二组 Configuration confc = new Configuration(false); confc.set("fs.defaultFS", "hdfs://node01:8020"); confc.set("dfs.blocksize", "1048576"); FileSystem fsc = FileSystem.get(confc); System.out.println(fsc.getDefaultBlockSize()); Configuration confd = new Configuration(false); confd.set("fs.defaultFS", "hdfs://node01:8020"); confd.set("dfs.blocksize", "134217728"); FileSystem fsd = FileSystem.get(confd); System.out.println(fsd.getDefaultBlockSize()); //第三组 Configuration confe = new Configuration(false); confe.set("fs.defaultFS", "hdfs://192.168.109.51:8020"); confe.set("dfs.blocksize", "134217728"); FileSystem fse = FileSystem.get(confe); System.out.println(fse.getDefaultBlockSize()); Configuration conff = new Configuration(false); conff.set("fs.defaultFS", "hdfs://192.168.109.51:8020"); conff.set("dfs.blocksize", "1048576"); FileSystem fsf = FileSystem.get(conff); System.out.println(fsf.getDefaultBlockSize());
//输出
System.out.println(fsa);
System.out.println(fsb);
System.out.println(fsc);
System.out.println(fsd);
System.out.println(fse);
System.out.println(fsf);
此次测试得到了预期的结果:
134217728
134217728
1048576
1048576
134217728
134217728
DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_1193042798_1, ugi=root (auth:SIMPLE)]] DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_1193042798_1, ugi=root (auth:SIMPLE)]] DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1041604824_1, ugi=root (auth:SIMPLE)]] DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1041604824_1, ugi=root (auth:SIMPLE)]] DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1719045568_1, ugi=root (auth:SIMPLE)]] DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_-1719045568_1, ugi=root (auth:SIMPLE)]]
从FileSystem对象的id能够看出, 相同地址获取的对象确实是同一对象, 至此, bug的产生已经能够解释的清楚了
[解决bug后的思考]
从最后的测试的结果能够看出, 源码的实现中有缓存处理, 当已经链接过一次以后, 再次获取FileSystem对象时并不会读取configuration中的参数, 只是根据地址与对象, 从相似于kv对的关系返回真实的FileSystem对象.
在debug模式运行代码会发现, 第一次根据配置生成FileSystem对象时有大约10s的延时, 这应该是服务器通信形成的, 由于服务器通信的时间成本过高, 因此才会采起这种缓存的方式返回对象.
通常使用中并不会对配置参数作调整, 所以这种实现方式不能说有问题, 可是若是须要临时更改配置参数时, 则需对这个问题当心一些.
最后, 感谢 尚学堂周老师,在此次解决bug时提供的帮助与思路.
如需下载代码和hadoop安装文件下载:
http://www.bjsxt.com/2015/down_0526/41.html