web-dev-qa-db-fra.com

Spark lit le fichier de S3 en utilisant sc.textFile ("s3n: // ...)

Essayer de lire un fichier situé dans S3 en utilisant spark-Shell:

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 ...

L'exception IOException : Aucun système de fichiers pour le schéma: s3n une erreur s'est produite lors de:

  • Spark 1.31 ou 1.40 sur la machine de développement (pas de librairies Hadoop)
  • Exécution de Hortonworks Sandbox HDP v2.2.4 (Hadoop 2.60) intégrant Spark 1.2.1 prêt à l'emploi).
  • Utilisation du schéma s3: // ou s3n: //

Quelle est la cause de cette erreur? Dépendance manquante, configuration manquante ou mauvaise utilisation de sc.textFile()?

Ou peut-être est-ce dû à un bogue qui affecte Spark build spécifique à Hadoop 2.60 car ceci post semble suggérer. Je vais essayer Spark pour Hadoop 2.40 pour voir si cela résout le problème.

43
Polymerase

Confirmation que cela est lié à Spark construit par rapport à Hadoop 2.60. Vient d'installer Spark 1.4.0 "Pré-construit pour Hadoop 2.4 et versions ultérieures" (au lieu de Hadoop 2.6) Et le code fonctionne maintenant bien.

sc.textFile("s3n://bucketname/Filename") pose maintenant une autre erreur:

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

Le code ci-dessous utilise le format d'URL S3 pour indiquer que Spark peut lire le fichier S3. À l'aide de la machine de développement (pas de bibliothèque 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

Encore mieux : le code ci-dessus contenant les informations d'identification AWS dans l'URI S3N sera rompu si la clé secrète AWS comporte un "/" avant. La configuration des informations d'identification AWS dans SparkContext résoudra le problème. Le code fonctionne que le fichier S3 soit public ou privé.

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

Bien que cette question ait déjà été acceptée, je pense que les détails exacts de la raison pour laquelle cela se produit manquent encore. Je pense donc qu'il pourrait y avoir une place pour une autre réponse.

Si vous ajoutez la dépendance requise hadoop-aws , votre code devrait fonctionner.

À partir de Hadoop 2.6.0, le connecteur s3 FS a été déplacé vers une bibliothèque distincte appelée hadoop-aws. Il existe également un Jira pour cela: Move s3-related FS code de connecteur pour hadoop-aws .

Cela signifie que toute version de spark créée avec Hadoop 2.6.0 ou une version plus récente devra utiliser une autre dépendance externe pour pouvoir se connecter au système de fichiers S3.
Voici un exemple sbt que j’ai essayé et qui fonctionne normalement avec Apache Spark 1.6.2 construit contre Hadoop 2.6.0:

libraryDependencies + = "org.Apache.hadoop"% "hadoop-aws"% "2.6.0"

Dans mon cas, j'ai rencontré quelques problèmes de dépendances, j'ai donc résolu en ajoutant l'exclusion:

libraryDependencies + = "org.Apache.hadoop"% "hadoop-aws"% "2.6.0" exclude ("Tomcat", "jasper-compiler") excludeAll ExclusionRule (organization = "javax.servlet")

Sur une note connexe, je n'ai pas encore essayé, mais il est recommandé d'utiliser le système de fichiers "s3a" et non "s3n" à partir de Hadoop 2.6.0.

La troisième génération, s3a: système de fichiers. Conçu pour être un commutateur en remplacement de s3n :, cette liaison de système de fichiers prend en charge des fichiers plus volumineux et promet de meilleures performances.

33

Vous pouvez ajouter le paramètre --packages avec le fichier jar approprié: à votre soumission:

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

Ceci est un exemple de code spark qui peut lire les fichiers présents sur 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)
8
Kaab Awan

Couru dans le même problème dans Spark 2.0.2. Résolu en le nourrissant les bocaux. Voici ce que j'ai couru:

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

évidemment, vous devez avoir les pots dans le chemin où vous utilisez spark-Shell de

6
user592894

J'ai dû copier les fichiers jar d'un téléchargement hadoop dans le $SPARK_HOME/jars répertoire. En utilisant le --jars drapeau ou le --packages Le drapeau pour spark-submit n'a pas fonctionné.

Détails:

  • Spark 2.3.0
  • Hadoop téléchargé était 2.7.6
  • Deux fichiers JAR copiés provenaient de (hadoop dir)/share/hadoop/tools/lib/
    • aws-Java-sdk-1.7.4.jar
    • hadoop-aws-2.7.6.jar
6
James D

Il y a un Spark JIRA, SPARK-7481 , ouvert à compter d'aujourd'hui, le 20 octobre 2016, pour ajouter un module de nuage d'étincelles incluant des dépendances transitives sur tout ce qui concerne s3a et Azure wasb: besoin, avec des tests.

Et un Spark PR pour correspondre. C’est ainsi que j’obtiens la prise en charge de s3a dans mes versions de spark

Si vous le faites à la main, vous devez obtenir le fichier JAR hadoop-aws de la version exacte du reste de vos fichiers JAR hadoop, et une version des fichiers JAR AWS 100% synchronisée avec celle contre laquelle Hadoop aws a été compilé. Pour 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

Collez tous ces éléments dans SPARK_HOME/jars. Exécutez spark avec vos informations d'identification configurées dans des variables Env ou dans spark-default.conf

le test le plus simple est de savoir si vous pouvez compter le nombre de lignes d’un fichier CSV.

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

Obtenez un numéro: tout va bien. Obtenez une trace de pile. Mauvaises nouvelles.

3
Steve Loughran

Pour Spark 1.4.x "Pré-construit pour Hadoop 2.6 et versions ultérieures":

Je viens de copier les paquets nécessaires S3, S3native de hadoop-aws-2.6.0.jar à spark-Assembly-1.4.1-hadoop2.6.0.jar.

Après cela, j'ai redémarré spark cluster et cela fonctionne. N'oubliez pas de vérifier le propriétaire et le mode du fichier d'assemblage.

2
Uster

Je faisais face au même problème. Cela a bien fonctionné après avoir défini la valeur de fs.s3n.impl et ajouté la dépendance 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 n'est pas un format de fichier par défaut. Vous devez construire votre version de Spark avec une version de Hadoop qui contient les bibliothèques supplémentaires utilisées pour la compatibilité AWS. Informations supplémentaires que j'ai trouvées ici, https: //www.hakkalabs. co/articles/faire-votre-local-hadoop-plus-comme-aws-élastique-mapreduce

1

Vous devez probablement utiliser s3a:/scheme au lieu de s3:/ou s3n:/Cependant, cela ne fonctionne pas immédiatement (pour moi) pour le spark Shell. Je vois ce qui suit trace de la pile:

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

Ce que je pense - vous devez ajouter manuellement la dépendance hadoop-aws manuellement http://search.maven.org/#artifactdetails|org.Apache.hadoop|hadoop-aws|2.7.1|jar Mais je ne sais pas comment l'ajouter correctement à spark-Shell.

1
pkozlov