Erreur Pyspark S3: java.lang.NoClassDefFoundError: com / amazonaws / services / s3 / model / MultiObjectDeleteException

Oct 27 2020

Échec de la configuration d'un cluster Spark capable de lire les fichiers AWS s3. Les logiciels que j'ai utilisés sont les suivants:

  1. hadoop-aws-3.2.0.jar
  2. aws-java-sdk-1.11.887.jar
  3. spark-3.0.1-bin-hadoop3.2.tgz

Utilisation de la version python: Python 3.8.6

from pyspark.sql import SparkSession, SQLContext
from pyspark.sql.types import *
from pyspark.sql.functions import *
import sys

spark = (SparkSession.builder
         .appName("AuthorsAges")
         .appName('SparkCassandraApp')
         .getOrCreate())


spark._jsc.hadoopConfiguration().set("fs.s3a.access.key", "access-key")
spark._jsc.hadoopConfiguration().set("fs.s3a.secret.key", "secret-key")
spark._jsc.hadoopConfiguration().set("fs.s3a.impl","org.apache.hadoop.fs.s3a.S3AFileSystem")
spark._jsc.hadoopConfiguration().set("com.amazonaws.services.s3.enableV4", "true")
spark._jsc.hadoopConfiguration().set("fs.s3a.aws.credentials.provider","org.apache.hadoop.fs.s3a.BasicAWSCredentialsProvider")
spark._jsc.hadoopConfiguration().set("fs.s3a.endpoint", "")


input_file='s3a://spark-test-data/Fire_Department_Calls_for_Service.csv'

file_schema = StructType([StructField("Call_Number",StringType(),True),
        StructField("Unit_ID",StringType(),True),
        StructField("Incident_Number",StringType(),True),
...
...
# Read file into a Spark DataFrame
input_df = (spark.read.format("csv") \
            .option("header", "true") \
            .schema(file_schema) \
            .load(input_file))

Le code échoue lorsqu'il commence à exécuter le spark.read.format. Il semble qu'il ne trouve pas la classe. java.lang.NoClassDefFoundError: com.amazonaws.services.s3.model.MultiObjectDeleteException

  File "<stdin>", line 1, in <module>
  File "/usr/local/spark/spark-3.0.1-bin-hadoop3.2/python/pyspark/sql/readwriter.py", line 178, in load
    return self._df(self._jreader.load(path))
  File "/usr/local/spark/spark-3.0.1-bin-hadoop3.2/python/lib/py4j-0.10.9-src.zip/py4j/java_gateway.py", line 1304, in __call__
  File "/usr/local/spark/spark-3.0.1-bin-hadoop3.2/python/pyspark/sql/utils.py", line 128, in deco
    return f(*a, **kw)
  File "/usr/local/spark/spark-3.0.1-bin-hadoop3.2/python/lib/py4j-0.10.9-src.zip/py4j/protocol.py", line 326, in get_return_value
py4j.protocol.Py4JJavaError: An error occurred while calling o51.load.
: java.lang.NoClassDefFoundError: com/amazonaws/services/s3/model/MultiObjectDeleteException
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at org.apache.hadoop.conf.Configuration.getClassByNameOrNull(Configuration.java:2532)
    at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:2497)
    at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2593)
    at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:3269)
    at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:3301)
    at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:124) at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:3352)
    at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:3320) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:479) at org.apache.hadoop.fs.Path.getFileSystem(Path.java:361) at org.apache.spark.sql.execution.streaming.FileStreamSink$.hasMetadata(FileStreamSink.scala:46)
    at org.apache.spark.sql.execution.datasources.DataSource.resolveRelation(DataSource.scala:366)
    at org.apache.spark.sql.DataFrameReader.loadV1Source(DataFrameReader.scala:297)
    at org.apache.spark.sql.DataFrameReader.$anonfun$load$2(DataFrameReader.scala:286) at scala.Option.getOrElse(Option.scala:189) at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:286) at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:232) 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:498) at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244) at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357) at py4j.Gateway.invoke(Gateway.java:282) at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132) at py4j.commands.CallCommand.execute(CallCommand.java:79) at py4j.GatewayConnection.run(GatewayConnection.java:238) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.ClassNotFoundException: com.amazonaws.services.s3.model.MultiObjectDeleteException at java.net.URLClassLoader.findClass(URLClassLoader.java:382) at java.lang.ClassLoader.loadClass(ClassLoader.java:418) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)

J'ai essayé de trouver la bonne combinaison pour les bocaux ci-dessus et python, mais je n'ai pas trouvé le bon mélange. J'obtiens toutes sortes de NoClassDefFoundError alors j'ai décidé d'utiliser les dernières versions de tous les jars et python que j'ai énumérés ci-dessus, mais toujours sans succès.

J'aimerais savoir quelles versions de jars et de python avez-vous utilisées pour configurer avec succès un cluster capable d'accéder à s3 en utilisant s3a via pyspark? Merci d'avance pour la réponse / aide.

Réponses

1 stevel Oct 30 2020 at 15:02

Hadoop 3.2 a été construit contre 1.11.563; collez le sdk ombré complet de cette version spécifique dans votre chemin de classe "aws-java-sdk-bundle" et tout devrait bien se passer.

Le SDK a été "pointilleux" dans le passé ... et la mise à jour provoque invariablement des surprises. Pour les curieux Qualifier une mise à jour du SDK AWS . Il est probablement temps que quelqu'un recommence.

1 PrateekDubey Oct 31 2020 at 19:02

J'ai pu résoudre ce problème sur Spark 3.0 / Hadoop 3.2. J'ai également documenté ma réponse ici - Erreur AWS EKS Spark 3.0, Hadoop 3.2 - NoClassDefFoundError: com / amazonaws / services / s3 / model / MultiObjectDeleteException

Utilisez le bundle AWS Java SDK suivant et ce problème sera résolu -

aws-java-sdk-bundle-1.11.874.jar (https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-bundle/1.11.874)

banjoman Oct 27 2020 at 23:04

J'ai donc tout nettoyé et réinstallé les versions suivantes de jars et cela a fonctionné: hadoop-aws-2.7.4.jar, aws-java-sdk-1.7.4.2.jar. Version d'installation de Spark: spark-2.4.7-bin-hadoop2.7. Version Python: Python 3.6.