使用Java API将数据上传到HDFS

时间:2015-09-04 13:17:11

标签: java hadoop hdfs

我已经搜索了一段时间,但似乎没有任何解决方案对我有用。

非常简单 - 我想使用Java API将数据从本地文件系统上传到HDFS。 Java程序将在已配置为通过shell(即hdfs dfs -ls等)与远程Hadoop集群通信的主机上运行。

我在项目中包含了以下依赖项:

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日)

我已删除了2个Hadoop依赖项 - 我现在只使用了一个:

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作业,但这些更改为我做了诀窍。

3 个答案:

答案 0 :(得分:1)

我不确定您所遵循的方法,但以下是使用java libs将数据上传到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详细信息将在运行时自动获取,您无需设置&#34; fs.defaultFS&#34; 。此外,如果您使用的是旧的hdfs版本,则可能需要使用&#34; fs.default.name&#34;而不是&#34; fs.defaultFS&#34;。如果您不确定hdfs端点,通常是hdfs namenode url。以下是之前类似问题copying directory from local system to hdfs java code

的示例

答案 1 :(得分:0)

两件事:

  1. 如果您要创建Hadoop客户端,最好添加 hadoop-client 依赖项。它包括所有子模块所需的依赖项。 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
  3. 如果您查看createClassLoader课程中的RunJar方法,您会注意到类路径中包含多个位置。

    然后,如果您使用 java -jar 命令直接执行您的课程,您可能会忽略在hadoop中执行您的工作所需的所有其他必要步骤 hadoop jar 正在做。

答案 2 :(得分:0)

Kasa,你需要使用方法

public static FileSystem get(URI uri,Configuration conf)

要获得fs,如果使用java -jar命令,则必须使用uri参数。