2015-09-04 26 views
1

我已經搜索了一段時間,並沒有任何解決方案似乎適用於我。使用Java API將數據上傳到HDFS

非常簡單 - 我想使用Java API將數據從本地文件系統上傳到HDFS。 Java程序將在已配置爲通過shell與遠程Hadoop羣集通信的主機(即hdfs dfs -ls等)上運行。

我已經包括在我的項目下面的依賴關係:

hadoop-core:1.2.1 
hadoop-common:2.7.1 
hadoop-hdfs:2.7.1 

我有一些代碼如下所示:

File localDir = ...; 
File hdfsDir = ...; 
Path localPath = new Path(localDir.getCanonicalPath()); 
Path hdfsPath = new Path(hdfsDir.getCanonicalPath()); 
Configuration conf = new Configuration(); 
conf.set("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName()); 
conf.set("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName()); 
Filesystem fs = FileSystem.get(configuration); 
fs.getFromLocalFile(localPath, hdfsPath); 

本地數據沒有被複制到Hadoop集羣,但沒有報告錯誤,也不會引發異常。我已啓用TRACE登錄org.apache.hadoop包。我看到以下輸出:

DEBUG Groups:139 - Creating new Groups object 
DEBUG Groups:139 - Creating new Groups object 
DEBUG Groups:59 - Group mapping impl=org.apache.hadoop.security.ShellBasedUnixGroupsMapping; cacheTimeout=300000 
DEBUG Groups:59 - Group mapping impl=org.apache.hadoop.security.ShellBasedUnixGroupsMapping; cacheTimeout=300000 
DEBUG UserGroupInformation:147 - hadoop login 
DEBUG UserGroupInformation:147 - hadoop login 
DEBUG UserGroupInformation:96 - hadoop login commit 
DEBUG UserGroupInformation:96 - hadoop login commit 
DEBUG UserGroupInformation:126 - using local user:UnixPrincipal: willra05 
DEBUG UserGroupInformation:126 - using local user:UnixPrincipal: willra05 
DEBUG UserGroupInformation:558 - UGI loginUser:<username_redacted> 
DEBUG UserGroupInformation:558 - UGI loginUser:<username_redacted> 
DEBUG FileSystem:1441 - Creating filesystem for file:/// 
DEBUG FileSystem:1441 - Creating filesystem for file:/// 
DEBUG FileSystem:1290 - Removing filesystem for file:/// 
DEBUG FileSystem:1290 - Removing filesystem for file:/// 
DEBUG FileSystem:1290 - Removing filesystem for file:/// 
DEBUG FileSystem:1290 - Removing filesystem for file:/// 

任何人都可以幫助我解決此問題嗎?

編輯1:(2015年9月15日)

我已經刪除了Hadoop的依賴關係的2 - 我只使用一個現在:

hadoop-core:1.2.1 

我的代碼是現在以下:

File localDir = ...; 
File hdfsDir = ...; 
Path localPath = new Path(localDir.getCanonicalPath()); 
Path hdfsPath = new Path(hdfsDir.getCanonicalPath()); 
Configuration conf = new Configuration(); 
fs.getFromLocalFile(localPath, hdfsPath); 

我以前執行我用下面的命令應用:

$ java -jar <app_name>.jar <app_arg1> <app_arg2> ... 

現在我用這個命令執行它:

$ hadoop jar <app_name>.jar <app_arg1> <app_arg2> ... 

有了這些變化,預期我的應用程序現在HDFS進行交互。據我所知,hadoop jar命令僅適用於打包爲可執行jar的Map Reduce作業,但這些更改對我來說是個竅門。

+0

hadoop命令在類路徑中包含hadoop類,並且如果需要將jar拆開並重新打包以包含某些庫。在enh,haddop命令將執行java命令,但會使用額外的對象/配置。 – RojoSam

+0

我已經使用Maven Shade插件將我的程序打包爲一個胖罐子。你是指別的東西嗎?如果是這樣,請澄清。 – Kasa

回答

1

我不知道你在下面的辦法,但下面是單向的數據可以使用Java庫上傳到HDFS:

//imports required 
import org.apache.hadoop.conf.Configuration; 
import org.apache.hadoop.fs.FileSystem; 

//some class here ..... 
Configuration conf = new Configuration(); 
conf.set("fs.defaultFS", <hdfs write endpoint>); 
FileSystem fs = FileSystem.get(conf); 
fs.copyFromLocalFile(<src>, <dst>); 

此外,如果有Hadoop的的conf本地XMLS,您可以將其在你的課程路徑中。然後,hadoop fs的細節將在運行時自動提取,並且您不需要設置「fs.defaultFS」。另外,如果您使用的是舊版hdfs版本,則可能需要使用「fs.default.name」而不是「fs.defaultFS」。如果您不確定hdfs端點,通常是hdfs namenode url。下面是例子,以前類似的問題copying directory from local system to hdfs java code

+0

我的程序使用Maven Shade插件打包爲一個胖罐子。我注意到,如果我嘗試使用'$ java -jar <程序名> .jar'執行jar,程序不會按預期執行,但如果我用'$ hadoop jar <程序名> .jar'執行jar,它會執行我的意圖。你知道爲什麼嗎? – Kasa

0

兩件事情:

  1. 如果要創建一個Hadoop客戶端,它可以更好地增加Hadoop的客戶依賴。它包含了所有需要依賴的子模塊。 https://github.com/apache/hadoop/blob/2087eaf684d9fb14b5390e21bf17e93ac8fea7f8/hadoop-client/pom.xml。除非Jar的大小是一個問題,如果你確信你不需要另一個依賴。
  2. 當您使用hadoop命令執行作業時,它所執行的類是RunJar而不是您的驅動程序類。然後RunJar執行你的工作。有關詳細信息,你可以在這裏看到的代碼:https://github.com/apache/hadoop/blob/2087eaf684d9fb14b5390e21bf17e93ac8fea7f8/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/RunJar.java#L139

如果您查看在RunJar類的createClassLoader方法,你會發現,被列入類路徑幾個地點。

然後,如果你是直接執行你的類使用Java的罐子命令你可能會忽略其他所有需要的步驟,以在Hadoop的那Hadoop的罐子正在做執行作業。

+0

感謝您的澄清。讓我退後一步:我是否應該使用'hadoop jar'命令來運行我的程序?我的程序確實與HDFS交互,但它不是一個Map Reduce作業。根據我的理解,'hadoop jar'命令用於運行Map Reduce作業。恰巧我的程序的代碼通過這個命令正確執行(與'java -jar'命令相反),因爲某些其他事情被添加到類路徑中。 – Kasa

+0

如果您的項目不需要在**分佈式環境**(MapReduce或Yarn)中運行,那麼不需要使用** hadoop jar **來執行它。你只需要確定** hadoop-client **依賴項包含在你的項目中。對我來說,簡單的方法是使用** maven **來管理依賴關係。使用聲明執行項目:'mvn exec:java -Dexec.mainClass =「com.module.Main」' – RojoSam

+0

是的,謝謝你的建議。切換到'hadoop-client'之後,我最終得到了一個關於'HADOOP_HOME'和/或'hadoop.home.dir'沒有被設置的'IOException'。我是否缺少一些額外的配置,現在我正在使用'java -jar'而不是'hadoop jar'? – Kasa

0

開賽,您需要使用方法

public static FileSystem get(URI uri,Configuration conf) 

得到fs,如果使用java -jar命令的URI params爲必要。