web-dev-qa-db-ja.com

Spark sc.textFileを使用してS3からファイルを読み取ります( "s3n:// ...)

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:スキームのFileSystemがありません:s3nエラーが発生しました:

  • 開発マシン上のSpark 1.31または1.40(Hadoopライブラリなし)
  • すぐに統合されるSpark 1.2.1を統合する Hortonworks Sandbox HDP v2.2.4 (Hadoop 2.60)から実行
  • S3://またはs3n://スキームを使用する

このエラーの原因は何ですか?依存関係の欠落、構成の欠落、またはsc.textFile()の誤用

または、これは、Hadoop 2.60に固有のSparkビルドに影響するバグが原因である可能性があります。これは post が示唆しているためです。 Hadoop 2.40のSparkを試して、これで問題が解決するかどうかを確認します。

43
Polymerase

これが、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:[email protected]/SafeAndSound_Lyrics.txt")
lyrics: org.Apache.spark.rdd.RDD[String] = MapPartitionsRDD[3] at textFile at <console>:21

scala> lyrics.count
res1: Long = 9

Even Better: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
43
Polymerase

この質問にはすでに受け入れられた答えがあるにもかかわらず、なぜこれが起こっているのかについての正確な詳細はまだ失われていると思います。ですから、もう1つ答える場所があると思います。

必要な hadoop-aws 依存関係を追加すると、コードは機能するはずです。

Hadoop 2.6.0以降、s3 FSコネクターはhadoop-awsと呼ばれる別のライブラリーに移動されました。そのためのJiraもあります: s3関連FSコネクタコードをhadoop-awsに移動

つまり、Hadoop 2.6.0以降に対してビルドされたすべてのバージョンのsparkは、S3ファイルシステムに接続するために別の外部依存関係を使用する必要があります。
これは私が試したsbtの例で、Apache Spark 1.6.2をHadoop 2.6.0に対してビルドして使用しました。

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")

その他の関連する注意事項については、まだ試していないが、Hadoop 2.6.0以降は「s3n」ファイルシステムではなく「s3a」を使用することをお勧めします。

第三世代、s3a:ファイルシステム。 s3n:に代わるスイッチとして設計されたこのファイルシステムバインディングは、より大きなファイルをサポートし、より高いパフォーマンスを約束します。

適切な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
15
Andrew K

これは、s3にあるファイルを読み取ることができるサンプルsparkコードです

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)
8
Kaab Awan

Spark 2.0.2で同じ問題に遭遇しました。 jarにフィードすることで解決しました。私が実行したものは次のとおりです。

$ 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が必要です

6
user592894

Jarファイルをhadoopダウンロードから$SPARK_HOME/jarsディレクトリにコピーする必要がありました。 spark-submitに--jarsフラグまたは--packagesフラグを使用しても機能しませんでした。

詳細:

  • Spark 2.3.0
  • ダウンロードしたHadoopは2.7.6でした
  • コピーされた2つのjarファイルは(hadoop dir)/share/hadoop/tools/lib/ からのものでした
    • aws-Java-sdk-1.7.4.jar
    • hadoop-aws-2.7.6.jar
6
James D

Spark JIRA、 SPARK-7481 、2016年10月20日現在、s3aおよびAzure wasbに対する推移的な依存関係を含むスパーククラウドモジュールを追加します。 :テストと一緒に必要。

そして、一致する Spark PR 。これは、sparkビルドにs3aサポートを取得する方法です

手作業で行う場合は、残りのhadoop JARの正確なバージョンのhadoop-aws JARと、Hadoop awsのコンパイル対象と完全に同期したAWS JARのバージョンを取得する必要があります。 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()

数字を取得:すべて順調です。スタックトレースを取得します。悪いニュース。

3
Steve Loughran

Spark 1.4.xの場合:「Hadoop 2.6以降用に事前に構築された」:

必要なS3、S3nativeパッケージをhadoop-aws-2.6.0.jarからspark-Assembly-1.4.1-hadoop2.6.0.jarにコピーしました。

その後、sparkクラスターを再起動しましたが、動作します。アセンブリjarの所有者とモードを確認することを忘れないでください。

2
Uster

私は同じ問題に直面していました。 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")
2
PDerp15

S3Nはデフォルトのファイル形式ではありません。 AWS互換性のために使用される追加のライブラリを持つHadoopのバージョンでSparkのバージョンをビルドする必要があります。ここで見つけた追加情報 https://www.hakkalabs.co/articles/making-your-local-hadoop-more-like-aws-elastic-mapreduce

おそらく、s3:/またはs3n:/の代わりにs3a:/スキームを使用する必要がありますが、spark Shellの場合は(私にとっては)そのままでは機能しません。次のスタックトレースが表示されます。

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 しかし、私はそれをスパークシェルに適切に追加する方法がわかりません。

1
pkozlov