Spark不会从s3读取/写入信息(ResponseCode = 400,ResponseMessage = Bad Request)

时间:2017-09-11 09:21:28

标签: java hadoop apache-spark amazon-s3

我实施了火花应用程序。 我创建了火花背景:

    private JavaSparkContext createJavaSparkContext() {
            SparkConf conf = new SparkConf();
            conf.setAppName("test");
            if (conf.get("spark.master", null) == null) {
                conf.setMaster("local[4]");
            }
            conf.set("fs.s3a.awsAccessKeyId", getCredentialConfig().getS3Key());
            conf.set("fs.s3a.awsSecretAccessKey", getCredentialConfig().getS3Secret());
            conf.set("fs.s3a.endpoint", getCredentialConfig().getS3Endpoint());

            return new JavaSparkContext(conf);
        }

我尝试通过spark数据集API(Spark SQL)从s3获取数据:

     String s = "s3a://" + getCredentialConfig().getS3Bucket();
     Dataset<Row> csv = getSparkSession()
                        .read()
                        .option("header", "true")
                        .csv(s + "/dataset.csv");

     System.out.println("Read size :" + csv.count());

有一个错误:

Exception in thread "main" com.amazonaws.services.s3.model.AmazonS3Exception: Status Code: 400, AWS Service: Amazon S3, AWS Request ID: 1A3E8CBD4959289D, AWS Error Code: null, AWS Error Message: Bad Request, S3 Extended Request ID: Q1Fv8sNvcSOWGbhJSu2d3Nfgow00388IpXiiHNKHz8vI/zysC8V8/YyQ1ILVsM2gWQIyTy1miJc=

Hadoop版本:2.7

AWS端点:s3.eu-central-1.amazonaws.com

(在hadoop 2.8上 - 一切正常)

1 个答案:

答案 0 :(得分:1)

问题是:法兰克福不支持s3n。需要使用s3a。 而这个地区有V4版本。 http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region

欧盟(法兰克福)eu-central-1仅限第4版

这意味着需要在aws客户端上启用它。 需要添加系统属性

com.amazonaws.services.s3.enableV4 - &gt;真

conf.set("com.amazonaws.services.s3.enableV4", "true");//doesn't work for me

在我使用过的本地机器上:

System.setProperty("com.amazonaws.services.s3.enableV4", "true");

要在AWS EMR上运行,需要将参数添加到spark-submit:

spark.executor.extraJavaOptions=-Dcom.amazonaws.services.s3.enableV4=true
spark.driver.extraJavaOptions=-Dcom.amazonaws.services.s3.enableV4=true

此外,您应该为文件系统添加类实现:

conf.set("spark.hadoop.fs.s3a.impl", org.apache.hadoop.fs.s3a.S3AFileSystem.class.getName());
conf.set("spark.hadoop.fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName());
conf.set("spark.hadoop.fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName());