使用 sc.textFile (“s3n://...”) 从 S3 生成读取文件

尝试使用 spark-shell 读取位于 S3 中的文件:

scala> val myRdd = sc.textFile("s3n://myBucket/myFile1.log")
lyrics: org.apache.spark.rdd.RDD[String] = s3n://myBucket/myFile1.log MappedRDD[55] at textFile at <console>:12

scala> myRdd.count
java.io.IOException: No FileSystem for scheme: s3n
    at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2607)
    at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2614)
    at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:91)
    ... etc ...

IOException: No FileSystem for scheme: s3n 错误发生在:

  • 开发机器上的 Spark 1.31 或 1.40(无 Hadoop 库)
  • Hortonworks 沙盒 HDP v2.2.4 (Hadoop 2.60) 运行,该版本开箱即用地集成了 Spark 1.2.1
  • 使用 s3:// 或 s3n:// 方案

此错误的原因是什么?缺少依赖项、缺少配置或误用 ?sc.textFile()

或者这可能是由于一个影响特定于Hadoop 2.60的Spark构建的错误,正如这篇文章所暗示的那样。我将尝试Spark for Hadoop 2.40,看看这是否能解决问题。


答案 1

确认这与针对 Hadoop 2.60 的 Spark 构建有关。刚刚安装了 Spark 1.4.0“为 Hadoop 2.4 及更高版本预构建”(而不是 Hadoop 2.6)。代码现在工作正常。

sc.textFile("s3n://bucketname/Filename")现在引发另一个错误:

java.lang.IllegalArgumentException: AWS Access Key ID and Secret Access Key must be specified as the username or password (respectively) of a s3n URL, or by setting the fs.s3n.awsAccessKeyId or fs.s3n.awsSecretAccessKey properties (respectively).

下面的代码使用 S3 URL 格式来显示 Spark 可以读取 S3 文件。使用开发机器(没有Hadoop库)。

scala> val lyrics = sc.textFile("s3n://MyAccessKeyID:MySecretKey@zpub01/SafeAndSound_Lyrics.txt")
lyrics: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[3] at textFile at <console>:21

scala> lyrics.count
res1: Long = 9

甚至更好:如果 AWS Secret Key 具有正向“/”,则上面在 S3N URI 中内联的 AWS 凭证的代码将中断。在 SparkContext 中配置 AWS 凭证将修复此问题。无论 S3 文件是公用文件还是私有文件,代码都有效。

sc.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", "BLABLA")
sc.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey", "....") // can contain "/"
val myRDD = sc.textFile("s3n://myBucket/MyFilePattern")
myRDD.count

答案 2

尽管这个问题已经有了一个公认的答案,但我认为为什么会发生这种情况的确切细节仍然缺失。所以我认为可能有一个地方可以再回答一个。

如果您添加所需的 hadoop-aws 依赖项,您的代码应该可以正常工作。

从 Hadoop 2.6.0 开始,s3 FS 连接器已移至名为 hadoop-aws 的单独库中。还有一个Jira:将与s3相关的FS连接器代码移动到hadoop-aws

这意味着任何针对Hadoop 2.6.0或更高版本构建的spark版本都必须使用另一个外部依赖项才能连接到S3文件系统。
以下是我尝试过的sbt示例,并且正在使用针对Hadoop 2.6.0构建的Apache Spark 1.6.2按预期工作:

libraryDependencies += “org.apache.hadoop” % “hadoop-aws” % “2.6.0”

在我的情况下,我遇到了一些依赖性问题,所以我通过添加排除来解决:

libraryDependencies += “org.apache.hadoop” % “hadoop-aws” % “2.6.0” exclude(“tomcat”, “jasper-compiler”) excludeAll ExclusionRule(organization = “javax.servlet”)

在其他相关说明中,我还没有尝试过,但建议使用“s3a”而不是“s3n”文件系统启动Hadoop 2.6.0。

第三代,s3a:文件系统。此文件系统绑定旨在替代 s3n: 的交换机,支持更大的文件并承诺更高的性能。


推荐