spark 2.3.0,aws-sdk-java 1.7.4-由于AmazonS3Exception错误的请求,s3a读取失败?

时间:2018-06-20 08:08:12

标签: apache-spark amazon-s3

在使用spark 2.3.0时,我尝试从s3中读取hadoop-aws 2.7.6

spark.sparkContext.textFile("s3a://ap-northeast-2-bucket/file-1").take(10)

但是引发了AmazonS3Exception。

com.amazonaws.services.s3.model.AmazonS3Exception: Status Code: 400, AWS Service: Amazon S3, AWS Request ID: 202ABEDF0E955321, AWS Error Code: null, AWS Error Message: Bad Request
  at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:798)
  at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:421)
  at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:232)
  at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3528)
  ...

我使用实例配置文件启动了ec2实例,所以AWS开发工具包正在使用InstaneProfileCredential,并且可以在控制台中成功使用AWS CLI

aws s3 ls ap-northeast-2-bucket 
aws s3 cp s3://ap-northeast-2-bucket/file-a file-a 

我确实在spark-defaults.conf中将fs.s3a.endpoint设置为s3.ap-northeast-2.amazonaws.com

# spark-defaults.conf
spark.hadoop.fs.s3a.endpoint    s3.ap-northeast-2.amazonaws.com

1 个答案:

答案 0 :(得分:1)

这是由许多事实共同造成的。

我正在使用带有hadoop 2.7的spark 2.3.0。因此,我使用的是hadoop-aws 2.7.6,然后依赖于aws-java-sdk版本是1.7.4。

我的存储桶位于首尔(ap-northeast-2)和(首尔和法兰克福)地区,仅支持V4签名机制。因此,我应该将aws-sdk的端点设置为正确使用V4。可以通过设置hadoop conf

来解决此问题。
spark.hadoop.fs.s3a.endpoint    s3.ap-northeast-2.amazonaws.com

2016年6月之前发布的aws-java-sdk默认使用V2签名机制。因此,我应该明确设置aws-sdk以使用V4。这可以通过设置java系统属性来解决。

import com.amazonaws.SDKGlobalConfiguration
System.setProperty(SDKGlobalConfiguration.ENABLE_S3_SIGV4_SYSTEM_PROPERTY, "true")

如果两个修复程序均未应用,则会发生BadRequest错误。