AmazonS3Exception Bad Request:从法兰克福s3到emr hdfs的distcp失败

时间:2016-01-15 12:08:14

标签: hadoop amazon-web-services amazon-s3 emr

我正在尝试将来自法兰克福(eu-central-1)的s3存储桶中的文件复制到我在爱尔兰通过EMR托管的hdfs(eu-west-1)。我尝试执行的复制命令:

hdfs dfs -cp "s3a://<bucket>/<file>" /user/hadoop/<file>

s3-dist-cp --src "s3a://<bucket>/" --dest hdfs:///user/hadoop/ --srcPattern <file>

hadoop distcp "s3a://<bucket>/<file>" /user/hadoop/<file>

在所有情况下(以及关于额外选项的各种排列以及所有这些命令上的s3,s3a,s3n)我确实得到类似以下异常:

16/01/15 11:48:24 ERROR tools.DistCp: Exception encountered
com.amazonaws.services.s3.model.AmazonS3Exception: Bad Request (Service: Amazon S3; Status Code: 400; Error Code: 400 Bad Request; Request ID: 4A77158C1BD71C29), S3 Extended Request ID:     LU41MspxqVnHqyaMreTvggRG480Wb9d+TBx1MAo5v/g9yz07mmPizcZVOtRMQ+GElXs8vl/WZXA=
        at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1219)
        at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:803)
        at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:505)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:317)
        at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3595)
        at com.amazonaws.services.s3.AmazonS3Client.headBucket(AmazonS3Client.java:1041)
        at com.amazonaws.services.s3.AmazonS3Client.doesBucketExist(AmazonS3Client.java:1013)
        at org.apache.hadoop.fs.s3a.S3AFileSystem.initialize(S3AFileSystem.java:154)
        at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2644)
        at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:90)
        at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2678)
        at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2660)
        at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:374)
        at org.apache.hadoop.fs.Path.getFileSystem(Path.java:296)
        at org.apache.hadoop.tools.GlobbedCopyListing.doBuildListing(GlobbedCopyListing.java:76)
        at org.apache.hadoop.tools.CopyListing.buildListing(CopyListing.java:84)
        at org.apache.hadoop.tools.DistCp.createInputFileListing(DistCp.java:353)
        at org.apache.hadoop.tools.DistCp.execute(DistCp.java:160)
        at org.apache.hadoop.tools.DistCp.run(DistCp.java:121)
        at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
        at org.apache.hadoop.tools.DistCp.main(DistCp.java:401)

所以我认为使用s3a在幕后使用亚马逊的sdk。经过大量的研究,我找到了推测的原因:

链接:Amazon s3a returns 400 Bad Request with Spark

链接:https://github.com/aws/aws-sdk-java/issues/360

总而言之,法兰克福和其他一些新的中心“只能”使用签名版本4,但所有命令hadoop cp,distcp或s​​3-dist-cp都可以使用版本2?

由于使用s3a正在使用aws sdk,我试图通过添加

来强制使用Signature V4
export JAVA_OPTS="-Dcom.amazonaws.services.s3.enableV4 -Dcom.amazonaws.services.s3.enforceV4"

但无济于事。

这个事实让我尝试做以上所有,但在eu-central-1中使用了一个 NOT 的存储桶,例如在欧洲西部1号。那很有效。所以我想这就是它?

这个问题有解决方法吗?有人经历过这个吗?

修改

一种可行的替代方法是使用aws cli将数据从s3下载到主服务器上然后使用,例如

hdfs dfs -put <src> <dst>

完成工作。但是,如果真的大量数据不适合主节点该怎么办?

1 个答案:

答案 0 :(得分:0)

我已设法通过指定端点将数据从s3,FRA获取到HDFS:

hdfs dfs -Dfs.s3a.awsAccessKeyId=<access key ID> -Dfs.s3a.awsSecretAccessKey=<secret acces key> -Dfs.s3a.endpoint=<s3 enpoint> -ls s3a://<bucket_name>/...

您不会也不应该在本地复制它。