在使用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
答案 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错误。