我现在已经搜索了一段时间,似乎没有一个解决方案适合我 .
非常简单 - 我想使用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集群,但未报告任何错误,也不会引发异常 . 我为 org.apache.hadoop
包启用了 TRACE
日志记录 . 我看到以下输出:
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:///
任何人都可以帮助我解决这个问题吗?
EDIT 1: (09/15/2015)
我删除了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 回答
我不确定你所遵循的方法,但下面是使用java libs将数据上传到hdfs的一种方法:
此外,如果您在本地使用hadoop conf xmls,则可以将它们包含在类路径中 . 然后,hadoop fs详细信息将在运行时自动获取,您无需设置"fs.defaultFS" . 此外,如果您在旧的hdfs版本中运行,则可能需要使用"fs.default.name"而不是"fs.defaultFS" . 如果您不确定hdfs endpoints ,通常是hdfs namenode url . 这是以前类似问题的例子copying directory from local system to hdfs java code
两件事情:
如果要创建Hadoop客户端,最好添加 hadoop-client 依赖项 . 它包括所有子模块所需的依赖项 . https://github.com/apache/hadoop/blob/2087eaf684d9fb14b5390e21bf17e93ac8fea7f8/hadoop-client/pom.xml . 除非Jar的大小是一个问题,如果你非常确定你不需要另一个依赖 .
使用
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
方法,您会注意到 classpath 中包含多个位置 .然后,如果您使用 java -jar 命令直接执行您的类,您可能会忽略在 hadoop jar 正在执行的hadoop中执行作业的所有其他必需步骤 .
卡萨,你需要使用这个方法
要获得
fs
,如果使用java -jar
命令,则必须使用uri参数 .