Hadoop 2.6.5 FileSystem和Configuration兩個物件的探究
版權宣告:本文為yunshuxueyuan原創文章,如需轉載,請標明出處。【http://www.cnblogs.com/sxt-zkys/】
QQ技術交流群:299142667
(結論)
通過尚學堂旗下雲數學院大資料周老師的講解可以得到以下結論:用相同的地址獲取的FileSystem物件是同一個; 第一次獲取物件後會有類似於快取的機制, 即使改變了configuration引數, 只要地址沒有發生變化, 獲取的FileSystem 物件不會改變.
[從bug開始]
在測試上傳資料到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來嘗試一下:
於是接著上段程式碼, 有了如下程式碼:
//初始化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);
然而結果並不樂觀:
此時其他的小夥伴@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
版權宣告:本文為yunshuxueyuan原創文章,如需轉載,請標明出處。【http://www.cnblogs.com/sxt-zkys/】
QQ技術交流群:299142667