1. 程式人生 > >Hadoop 2.6.5 FileSystem和Configuration兩個對象的探究

Hadoop 2.6.5 FileSystem和Configuration兩個對象的探究

family 上傳數據 大數 塊大小 緩存 完成 color span 小夥伴

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

Hadoop 2.6.5 FileSystem和Configuration兩個對象的探究