Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Can';t从HDFS复制到S3A_Java_Hadoop_Amazon S3_Hdfs - Fatal编程技术网

Java Can';t从HDFS复制到S3A

Java Can';t从HDFS复制到S3A,java,hadoop,amazon-s3,hdfs,Java,Hadoop,Amazon S3,Hdfs,我有一个类可以使用以下命令将目录内容从一个位置复制到另一个位置: import org.apache.hadoop.conf.Configuration; 导入org.apache.hadoop.fs.FileStatus; 导入org.apache.hadoop.fs.FileSystem; 导入org.apache.hadoop.fs.FileUtil; 导入org.apache.hadoop.fs.LocatedFileStatus; 导入org.apache.hadoop.fs.Path

我有一个类可以使用以下命令将目录内容从一个位置复制到另一个位置:

import org.apache.hadoop.conf.Configuration;
导入org.apache.hadoop.fs.FileStatus;
导入org.apache.hadoop.fs.FileSystem;
导入org.apache.hadoop.fs.FileUtil;
导入org.apache.hadoop.fs.LocatedFileStatus;
导入org.apache.hadoop.fs.Path;
导入org.apache.hadoop.fs.RemoteIterator;
类文件夹{
专用最终文件系统fs;
专用最终路径pth;
//…构造函数和其他方法
/**
*将内容(文件和子文件夹中的文件)复制到另一个文件夹。
*合并重叠的文件夹
*覆盖已经存在的文件
*@param将内容移动到的目标文件夹
*@失败时抛出IOException
*/
public void copyFilesTo(最终文件夹目标)引发IOException{
最终RemoteIterator iter=this.fs.listFiles(
这个.pth,
符合事实的
);
最终URI根=this.pth.toUri();
while(iter.hasNext()){
最终路径源=iter.next().getPath();
FileUtil.copy(
这个是.fs,
来源
destination.fs,
新路径(
destination.pth,
root.relativize(source.toUri()).toString()
),
错误的
符合事实的
this.fs.getConf()
);
}
}
}
该类在单元测试中使用本地(
文件://
)目录时工作正常, 但是当我试图在Hadoop集群中使用它从HDFS复制文件时(
hdfs:///tmp/result
)到AmazonS3(
s3a://mybucket/out
)它不会复制任何内容,也不会抛出错误,只是默默地跳过复制

当我将同一个类(同时使用HDFS或S3a文件系统)用于另一个目的时,它工作正常,因此这里的配置和
fs
引用应该可以

我做错了什么?如何将文件从HDFS正确复制到S3A

我正在使用Hadoop 2.7.3


更新 我在
copyFilesTo
方法中添加了更多日志,以记录
目标
变量(并在不更改代码的情况下提取了
rebase()
方法):

/**
*将内容(文件和子文件夹中的文件)复制到另一个文件夹。
*合并重叠的文件夹
*覆盖已经存在的文件
*@param dst文件夹,内容将移动到该文件夹
*@失败时抛出IOException
*/
public void copyFilesTo(最终文件夹dst)引发IOException{
Logger.info(
这是“copyFilesTo(%s):从%s fs=%s”,
dst,this,this.hdfs
);
最终RemoteIterator iter=this.hdfs.listFiles(
这个.pth,
符合事实的
);
最终URI根=this.pth.toUri();
Logger.info(这是“copyFilesTo(%s):root=%s”,dst,root);
while(iter.hasNext()){
最终路径源=iter.next().getPath();
最终路径目标=Folder.rebase(dst.Path(),this.Path(),source);
Logger.info(
这是“copyFilesTo(%s):src=%s target=%s”,
dst、源、目标
);
FileUtil.copy(
这个.hdfs,
来源
dst.hdfs,
目标
错误的
符合事实的
this.hdfs.getConf()
);
}
}
/**
*使用root将目标URI的基更改为新基
*作为共同的道路。
*@param base新基地
*@param root公共根
*@param-target要重新设置基础的目标
*@返回路径与新基
*/
静态路径重基(最终路径基、最终路径根、最终路径目标){
返回新路径(
base,root.toUri().relativize(target.toUri()).toString()
);
}
在集群中运行后,我得到了以下日志:

io.Folder: copyFilesTo(hdfs:///tmp/_dst): from hdfs:///tmp/_src fs=DFS[DFSClient[clientName=DFSClient_NONMAPREDUCE_182008924_1, ugi=hadoop (auth:SIMPLE)]]
io.Folder: copyFilesTo(hdfs:///tmp/_dst): root=hdfs:///tmp/_src
INFO io.Folder: copyFilesTo(hdfs:///tmp/_dst): src=hdfs://ip-172-31-2-12.us-east-2.compute.internal:8020/tmp/_src/one.file target=hdfs://ip-172-31-2-12.us-east-2.compute.internal:8020/tmp/_src/one.file

我在
rebase()
方法中本地化了错误的代码,它在EMR集群中运行时无法正常工作,因为
RemoteIterator
正在以远程格式返回URI:
hdfs://ip-172-31-2-12.us-east-2.compute.internal:8020/tmp/_src/one.file
但此方法需要格式
hdfs:///tmp/_src/one.file
,这就是为什么它在本地使用
文件://
FS。

我没有看到任何明显的错误

  • 它是hdfs hdfs还是s3a-s3a
  • 升级hadoop版本;2.7.x已经过时了,尤其是S3A代码。这不太可能解决这个问题,但可以避免其他问题。升级后,切换到,它将对大型文件进行增量更新;当前,您的代码将把每个文件保存到/tmp的某个位置,然后在close()调用中上载它
  • 打开org.apache.hadoop.fs.s3a模块的日志记录,看看它说了什么

  • 我不确定这是否是最好的、完全正确的解决方案,但它对我很有效。其思想是在重定基址之前修复本地路径的主机和端口,工作的
    重定基址
    方法将是:

    /**
    *使用root将目标URI的基更改为新基
    *作为共同的道路。
    *@param base新基地
    *@param root公共根
    *@param-target要重新设置基础的目标
    *@返回路径与新基
    *@失败时抛出IOException
    */
    @SuppressWarnings(“PMD.DefaultPackage”)
    静态路径重基(最终路径基、最终路径根、最终路径目标)
    抛出IOException{
    最终URI=target.toUri();
    试一试{
    返回新路径(
    新路径(
    新的URIBuilder(base.toUri())
    .setHost(uri.getHost())
    .setPort(uri.getPort())
    .build()
    ),
    新路径(
    新乌里别尔