使用sc.textFile(" s3n:// ...)从S3读取Spark文件

时间:2015-06-15 17:23:22

标签: apache-spark rdd hortonworks-data-platform

尝试使用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:没有针对方案的文件系统:s3n 错误:

  • 开发机器上的Spark 1.31或1.40(没有Hadoop库)
  • Hortonworks Sandbox HDP v2.2.4(Hadoop 2.60)开始运行,它集成了Spark 1.2.1开箱即用
  • 使用s3://或s3n:// scheme

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

或者可能是因为这个post似乎暗示了影响Hadoop 2.60特有的Spark构建的错误。我将尝试Spark for Hadoop 2.40,看看这是否解决了这个问题。

13 个答案:

答案 0 :(得分:42)

确认这与针对Hadoop 2.60的Spark构建有关。刚刚安装了Spark 1.4.0 "Pre built for Hadoop 2.4 and later"(而不是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密钥具有转发“/”,则上述代码将在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

答案 1 :(得分:32)

尽管这个问题已经得到了接受,但我认为为什么会发生这种情况仍然缺失。所以我认为可能还有一个地方可以再提一个答案。

如果您添加了必需的hadoop-aws依赖项,那么您的代码应该有效。

启动Hadoop 2.6.0后,s3 FS连接器已移至名为hadoop-aws的独立库中。 还有一个Jira: Move s3-related FS connector code to 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:的交换机,支持更大的文件并承诺更高的性能。

答案 2 :(得分:15)

您可以使用相应的jar添加--packages参数: 你提交的内容:

bin/spark-submit --packages com.amazonaws:aws-java-sdk-pom:1.10.34,org.apache.hadoop:hadoop-aws:2.6.0 code.py

答案 3 :(得分:8)

这是一个示例火花代码,可以读取s3上的文件

val hadoopConf = sparkContext.hadoopConfiguration
hadoopConf.set("fs.s3.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem")
hadoopConf.set("fs.s3.awsAccessKeyId", s3Key)
hadoopConf.set("fs.s3.awsSecretAccessKey", s3Secret)
var jobInput = sparkContext.textFile("s3://" + s3_location)

答案 4 :(得分:6)

在Spark 2.0.2中遇到同样的问题。通过喂它罐子解决它。这就是我的目的:

$ spark-shell --jars aws-java-sdk-1.7.4.jar,hadoop-aws-2.7.3.jar,jackson-annotations-2.7.0.jar,jackson-core-2.7.0.jar,jackson-databind-2.7.0.jar,joda-time-2.9.6.jar

scala> val hadoopConf = sc.hadoopConfiguration
scala> hadoopConf.set("fs.s3.impl","org.apache.hadoop.fs.s3native.NativeS3FileSystem")
scala> hadoopConf.set("fs.s3.awsAccessKeyId",awsAccessKeyId)
scala> hadoopConf.set("fs.s3.awsSecretAccessKey", awsSecretAccessKey)
scala> val sqlContext = new org.apache.spark.sql.SQLContext(sc)
scala> sqlContext.read.parquet("s3://your-s3-bucket/")
显然,你需要在你从

运行spark-shell的路径中放入jar

答案 5 :(得分:4)

我不得不将hadoop下载的jar文件复制到$SPARK_HOME/jars目录中。使用--jars标志或--packages标志进行spark-submit不起作用。

详细说明:

  • Spark 2.3.0
  • Hadoop已下载为2.7.6
  • 复制的两个jar文件来自(hadoop dir)/share/hadoop/tools/lib/
    • AWS-java的SDK-1.7.4.jar
    • Hadoop的AWS-2.7.6.jar

答案 6 :(得分:3)

有一个Spark JIRA,SPARK-7481,于今天,2016年10月20日开放,用于添加一个火花云模块,其中包含对所有s3a和azure isb:need以及测试的传递依赖性。

要匹配Spark PR。这就是我在我的spark构建中获得s3a支持的方式

如果您手动执行此操作,则必须获得hadoop-aws JAR与您的hadoop JARS的其余部分具有的确切版本,并且AWS JAR的版本100%与编译的Hadoop aws同步。对于Hadoop 2.7。{1,2,3,...}

hadoop-aws-2.7.x.jar 
aws-java-sdk-1.7.4.jar
joda-time-2.9.3.jar
+ jackson-*-2.6.5.jar

将所有这些都粘贴到SPARK_HOME/jars中。使用在Env vars或spark-default.conf

中设置的凭据运行spark

最简单的测试是你可以进行CSV文件的行计数

val landsatCSV = "s3a://landsat-pds/scene_list.gz"
val lines = sc.textFile(landsatCSV)
val lineCount = lines.count()

得到一个数字:一切都很好。获取堆栈跟踪。坏消息。

答案 7 :(得分:2)

对于Spark 1.4.x“为Hadoop 2.6及更高版本预构建”:

我刚从hadoop-aws-2.6.0.jar复制了所需的S3,S3native软件包 火花组装1.4.1-hadoop2.6.0.jar。

之后我重新启动了火花集群,它确实有效。 不要忘记检查装配罐的所有者和模式。

答案 8 :(得分:1)

S3N不是默认文件格式。您需要使用Hadoop版本构建您的Spark版本,该版本具有用于AWS兼容性的附加库。我在此处找到的其他信息https://www.hakkalabs.co/articles/making-your-local-hadoop-more-like-aws-elastic-mapreduce

答案 9 :(得分:1)

您可能必须使用s3a:/ scheme而不是s3:/或s3n:/ 但是,对于火花壳来说,它不是开箱即用(对我来说)。我看到以下stacktrace:

java.lang.RuntimeException: java.lang.ClassNotFoundException: Class org.apache.hadoop.fs.s3a.S3AFileSystem not found
        at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2074)
        at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2578)
        at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2591)
        at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:91)
        at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2630)
        at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2612)
        at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:370)
        at org.apache.hadoop.fs.Path.getFileSystem(Path.java:296)
        at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:256)
        at org.apache.hadoop.mapred.FileInputFormat.listStatus(FileInputFormat.java:228)
        at org.apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.java:313)
        at org.apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:207)
        at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:219)
        at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:217)
        at scala.Option.getOrElse(Option.scala:120)
        at org.apache.spark.rdd.RDD.partitions(RDD.scala:217)
        at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:32)
        at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:219)
        at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:217)
        at scala.Option.getOrElse(Option.scala:120)
        at org.apache.spark.rdd.RDD.partitions(RDD.scala:217)
        at org.apache.spark.SparkContext.runJob(SparkContext.scala:1781)
        at org.apache.spark.rdd.RDD.count(RDD.scala:1099)
        at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:24)
        at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:29)
        at $iwC$$iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:31)
        at $iwC$$iwC$$iwC$$iwC$$iwC.<init>(<console>:33)
        at $iwC$$iwC$$iwC$$iwC.<init>(<console>:35)
        at $iwC$$iwC$$iwC.<init>(<console>:37)
        at $iwC$$iwC.<init>(<console>:39)
        at $iwC.<init>(<console>:41)
        at <init>(<console>:43)
        at .<init>(<console>:47)
        at .<clinit>(<console>)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.apache.spark.repl.SparkIMain$ReadEvalPrint.call(SparkIMain.scala:1065)
        at org.apache.spark.repl.SparkIMain$Request.loadAndRun(SparkIMain.scala:1338)
        at org.apache.spark.repl.SparkIMain.loadAndRunReq$1(SparkIMain.scala:840)
        at org.apache.spark.repl.SparkIMain.interpret(SparkIMain.scala:871)
        at org.apache.spark.repl.SparkIMain.interpret(SparkIMain.scala:819)
        at org.apache.spark.repl.SparkILoop.reallyInterpret$1(SparkILoop.scala:857)
        at org.apache.spark.repl.SparkILoop.interpretStartingWith(SparkILoop.scala:902)
        at org.apache.spark.repl.SparkILoop.command(SparkILoop.scala:814)
        at org.apache.spark.repl.SparkILoop.processLine$1(SparkILoop.scala:657)
        at org.apache.spark.repl.SparkILoop.innerLoop$1(SparkILoop.scala:665)
        at org.apache.spark.repl.SparkILoop.org$apache$spark$repl$SparkILoop$$loop(SparkILoop.scala:670)
        at org.apache.spark.repl.SparkILoop$$anonfun$org$apache$spark$repl$SparkILoop$$process$1.apply$mcZ$sp(SparkILoop.scala:997)
        at org.apache.spark.repl.SparkILoop$$anonfun$org$apache$spark$repl$SparkILoop$$process$1.apply(SparkILoop.scala:945)
        at org.apache.spark.repl.SparkILoop$$anonfun$org$apache$spark$repl$SparkILoop$$process$1.apply(SparkILoop.scala:945)
        at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135)
        at org.apache.spark.repl.SparkILoop.org$apache$spark$repl$SparkILoop$$process(SparkILoop.scala:945)
        at org.apache.spark.repl.SparkILoop.process(SparkILoop.scala:1059)
        at org.apache.spark.repl.Main$.main(Main.scala:31)
        at org.apache.spark.repl.Main.main(Main.scala)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:665)
        at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:170)
        at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:193)
        at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:112)
        at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassNotFoundException: Class org.apache.hadoop.fs.s3a.S3AFileSystem not found
        at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:1980)
        at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2072)
        ... 68 more

我的想法 - 您必须手动手动添加hadoop-aws依赖项http://search.maven.org/#artifactdetails|org.apache.hadoop|hadoop-aws|2.7.1|jar但我不知道如何正确地将它添加到spark-shell。

答案 10 :(得分:1)

我遇到了同样的问题。在设置fs.s3n.impl的值并添加hadoop-aws依赖项后,它工作正常。

sc.hadoopConfiguration.set("fs.s3n.awsAccessKeyId", awsAccessKeyId)
sc.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey", awsSecretAccessKey)
sc.hadoopConfiguration.set("fs.s3n.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem")

答案 11 :(得分:0)

  1. maven repository下载与您的hadoop版本匹配的hadoop-aws jar。
  2. 将罐子复制到$SPARK_HOME/jars的位置。

现在在您的Pyspark脚本中,设置AWS Access Key和Secret Access Key。

spark.sparkContext._jsc.hadoopConfiguration().set("fs.s3.awsAccessKeyId", "ACCESS_KEY")
spark.sparkContext._jsc.hadoopConfiguration().set("fs.s3.awsSecretAccessKey", "YOUR_SECRET_ACCESSS_KEY")

// where spark is SparkSession instance

对于Spark scala:

spark.sparkContext.hadoopConfiguration.set("fs.s3.awsAccessKeyId", "ACCESS_KEY")
spark.sparkContext.hadoopConfiguration.set("fs.s3.awsSecretAccessKey", "YOUR_SECRET_ACCESSS_KEY")

答案 12 :(得分:-1)

使用s3a而不是s3n。我在Hadoop工作上有类似的问题。从s3n切换到s3a后,它起作用了。

e.g。

S3A://myBucket/myFile1.log