Comment puis-je résoudre l'erreur « java.lang.ClassNotFoundException » dans Spark sur Amazon EMR ?

Lecture de 4 minute(s)
0

Je souhaite résoudre l'erreur « java.lang.ClassNotFoundException » dans Apache Spark sur Amazon EMR.

Brève description

L'erreur java.lang.ClassNotFoundException dans Spark se produit pour les raisons suivantes :

  • La tâche spark-submit ne trouve pas les fichiers pertinents dans le chemin de classe.
  • Une action d'amorçage ou une configuration personnalisée remplace les chemins de classe. Par conséquent, le chargeur de classe récupère uniquement les fichiers JAR qui existent à l'emplacement que vous avez spécifié dans votre configuration.

Résolution

Pour résoudre l'erreur java.lang.ClassNotFoundException, vérifiez la trace de pile pour trouver le nom de la classe manquante. Puis, ajoutez le chemin de votre fichier JAR personnalisé contenant la classe manquante au chemin de classe Spark. Vous pouvez ajouter le chemin de votre fichier JAR personnalisé sur un cluster en cours d'exécution, un nouveau cluster ou lorsque vous soumettez une tâche.

Ajouter votre chemin JAR personnalisé sur un cluster en cours d'exécution

Dans /etc/spark/conf/spark-defaults.conf, ajoutez le chemin de votre fichier JAR personnalisé aux noms de classe spécifiés dans la trace de pile d'erreur.

Exemple :

sudo vim /etc/spark/conf/spark-defaults.conf
spark.driver.extraClassPath <other existing jar locations>:example-custom-jar-path
spark.executor.extraClassPath <other existing jar locations>:example-custom-jar-path

Remarque : Remplacez example-custom-jar-path par votre chemin JAR personnalisé.

Ajouter votre chemin JAR personnalisé sur un nouveau cluster

Pour ajouter votre chemin JAR personnalisé aux chemins de classe existants dans /etc/spark/conf/spark-defaults.conf, fournissez un objet de configuration lorsque vous créez un nouveau cluster. Utilisez les versions 5.14.0 ou ultérieures d'Amazon EMR pour créer un nouveau cluster.

Pour Amazon EMR 5.14.0 à Amazon EMR 5.17.0, incluez les éléments suivants :

[  {
    "Classification": "spark-defaults",
    "Properties": {
      "spark.driver.extraClassPath": "/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/home/hadoop/extrajars/*",
      "spark.executor.extraClassPath": "/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/home/hadoop/extrajars/*"
    }
  }
]

Pour Amazon EMR 5.17.0 à Amazon EMR 5.18.0, incluez /usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar comme chemin JAR supplémentaire :

[  {
    "Classification": "spark-defaults",
    "Properties": {
      "spark.driver.extraClassPath": "/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar:/home/hadoop/extrajars/*",
      "spark.executor.extraClassPath": "/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar:/home/hadoop/extrajars/*"
    }
  }
]

Pour Amazon EMR 5.19.0 à Amazon EMR 5.32.0, mettez à jour le chemin du JAR comme suit :

[
  {
    "Classification": "spark-defaults",
    "Properties": {
      "spark.driver.extraClassPath": "/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:/usr/share/aws/emr/goodies/lib/emr-spark-goodies.jar:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar:/home/hadoop/extrajars/*",
      "spark.executor.extraClassPath": "/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:/usr/share/aws/emr/goodies/lib/emr-spark-goodies.jar:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar:/home/hadoop/extrajars/*"
    }
  }
]

Pour Amazon EMR 5.33.0 vers Amazon EMR 5.36.0, mettez à jour le chemin du JAR comme suit :

[
  {
    "Classification": "spark-defaults",
    "Properties": {
      "spark.driver.extraClassPath": "/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/goodies/lib/emr-spark-goodies.jar:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar:/home/hadoop/extrajars/",
      "spark.executor.extraClassPath": "/usr/lib/hadoop-lzo/lib/*:/usr/lib/hadoop/hadoop-aws.jar:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/goodies/lib/emr-spark-goodies.jar:/usr/share/aws/emr/security/conf:/usr/share/aws/emr/security/lib/*:/usr/share/aws/hmclient/lib/aws-glue-datacatalog-spark-client.jar:/usr/share/java/Hive-JSON-Serde/hive-openx-serde.jar:/usr/share/aws/sagemaker-spark-sdk/lib/sagemaker-spark-sdk.jar:/usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar:/home/hadoop/extrajars/"
    }
  }
]

Pour les versions 6.0.0 et ultérieures d'Amazon EMR, vous ne pouvez pas utiliser la configuration pour mettre à jour le chemin JAR car le fichier de configuration inclut plusieurs chemins JAR. En outre, la longueur de chaque configuration de propriété que vous mettez à jour ne peut pas dépasser 1 024 caractères. Pour transmettre l'emplacement JAR personnalisé à spark-defaults.conf, ajoutez une action d’amorçage. Pour plus d'informations, consultez la section Comment puis-je mettre à jour toutes les notes Amazon EMR après la phase de démarrage ?

Pour ajouter une action d'amorçage, consultez la section Ajouter des actions d'amorçage personnalisées, puis effectuez les actions suivantes :

  • Remplacez s3://example-bucket/Bootstraps/script_b.sh par votre chemin Amazon Simple Storage Service (Amazon S3).
  • Remplacez /home/hadoop/extrajars/* par le chemin de votre fichier JAR personnalisé.
  • Vérifiez que le rôle d'exécution Amazon EMR dispose des autorisations requises pour accéder au compartiment Amazon S3.
    Remarque : Lorsque vous ajoutez le script d’amorçage, celui-ci s'applique à la configuration Spark du cluster plutôt qu'à une tâche spécifique.

Exemple de script pour modifier /etc/spark/conf/spark-defaults.conf :

#!/bin/bash
#
# This is an example of script_b.sh for changing /etc/spark/conf/spark-defaults.conf
#
while [ ! -f /etc/spark/conf/spark-defaults.conf ]
do
  sleep 1
done
#
# Now the file is available, do your work here
#
sudo sed -i '/spark.*.extraClassPath/s/$/:\/home\/hadoop\/extrajars\/\*/' /etc/spark/conf/spark-defaults.conf
exit 0
Launch the EMR cluster and add a bootstrap action similar to the following:
#!/bin/bash
pwd
aws s3 cp s3://example-bucket/Bootstraps/script_b.sh .
chmod +x script_b.sh
nohup ./script_b.sh &

Remarque : Remplacez example-bucket par votre compartiment Amazon S3.

Ajoutez votre chemin JAR personnalisé lorsque vous soumettez une tâche

Pour ajouter votre chemin JAR personnalisé lorsque vous soumettez une tâche, exécutez la commande spark-submit avec l'option jars. Pour plus d'informations, consultez la page Lancement d'applications avec spark-submit sur le site Web d'Apache Spark.

spark-submit --deploy-mode client --class org.apache.spark.examples.SparkPi --master yarn spark-examples.jar 100 --jars example-custom-jar-path

Remarque : Remplacez example-custom-jar-path par votre chemin JAR personnalisé. Pour éviter les conflits de classes, n'incluez pas de fichiers JAR standard lorsque vous utilisez l'option jars. Par exemple, n'incluez pas le fichier spark-core.jar car il existe déjà dans le cluster. Pour en savoir plus, consultez la section Configurer Spark.

Informations connexes

Configuration de Spark sur le site Web d'Apache Spark

Comment puis-je corriger l’erreur « Container killed by YARN for exceeding memory limits » dans Spark sur Amazon EMR ?

AWS OFFICIEL
AWS OFFICIELA mis à jour il y a 3 mois