Hadoop 2.6.5 FileSystem和Configuration兩個物件的探究

雲數學院發表於2017-07-18

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

 

相關文章