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