2015-09-04 22 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为必要。