Wie löse ich die „java.lang.ClassNotFoundException“ in Spark auf Amazon EMR?

Lesedauer: 4 Minute
0

Wenn ich benutzerdefinierte JAR-Dateien in einem Spark-Submit- oder PySpark-Job auf Amazon EMR verwende, erhalte ich einen java.lang.ClassNotFoundException-Fehler.

Kurzbeschreibung

Dieser Fehler tritt auf, wenn eine der folgenden Bedingungen zutrifft:

  • Der Spark-Submit-Job kann die relevanten Dateien im Klassenpfad nicht finden.
  • Eine Bootstrap-Aktion oder eine benutzerdefinierte Konfiguration überschreibt die Klassenpfade. In diesem Fall nimmt der Klassenlader nur die JAR-Dateien auf, die an dem Speicherort vorhanden sind, den Sie in Ihrer Konfiguration angegeben haben.

Behebung

Überprüfen Sie den Stack-Trace, um den Namen der fehlenden Klasse zu finden. Fügen Sie dann den Pfad Ihres benutzerdefinierten JARs (das die fehlende Klasse enthält) zum Spark-Klassenpfad hinzu. Sie können dies tun, während der Cluster läuft, wenn Sie einen neuen Cluster starten oder wenn Sie einen Job einreichen.

Auf einem laufenden Cluster

Hängen Sie in /etc/spark/conf/spark-defaults.conf den Pfad Ihrer benutzerdefinierten JAR an die Klassennamen an, die im Error-Stack-Trace angegeben sind. Im folgenden Beispiel ist /home/hadoop/extrajars/* der benutzerdefinierte JAR-Pfad.

sudo vim /etc/spark/conf/spark-defaults.conf
spark.driver.extraClassPath <other existing jar locations>:/home/hadoop/extrajars/*
spark.executor.extraClassPath <other existing jar locations>:/home/hadoop/extrajars/*

Auf einem neuen Cluster

Hängen Sie den benutzerdefinierten JAR-Pfad an die vorhandenen Klassenpfade in /etc/spark/conf/spark-defaults.conf an, indem Sie beim Erstellen eines Clusters ein Konfigurationsobjekt angeben.

**Hinweis:**Um diese Option verwenden zu können, müssen Sie einen Cluster mit der Amazon EMR-Version 5.14.0 oder höher erstellen.

Fügen Sie für Amazon EMR 5.14.0 bis Amazon EMR 5.17.0 Folgendes hinzu:

[
  {
    "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/*"
    }
  }
]

Geben Sie für Amazon EMR 5.17.0 bis Amazon EMR 5.18.0 /usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar als zusätzlichen JAR-Pfad an:

[
  {
    "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/*"
    }
  }
]

Für Amazon EMR 5.19.0 bis Amazon EMR 5.32.0 aktualisieren Sie den JAR-Pfad wie folgt:

[
  {
    "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/*"
    }
  }
]

Für Amazon EMR 5.33.0 bis Amazon EMR 5.34.0 aktualisieren Sie den JAR-Pfad wie folgt:

[
  {
    "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/"
    }
  }
]

Für Amazon EMR Release-Version 6.0.0 und höher funktioniert die Aktualisierung des JAR-Pfads mithilfe der Konfiguration nicht. Bei diesen Versionen enthält die .conf-Datei mehrere JAR-Dateipfade. Außerdem darf die Länge der Konfiguration für jede Eigenschaft, die Sie aktualisieren, nicht mehr als 1024 Zeichen betragen. Sie können jedoch eine Bootstrap-Aktion hinzufügen, um den benutzerdefinierten JAR-Speicherort an spark-defaults.conf zu übergeben. Weitere Informationen finden Sie unter Wie aktualisiere ich alle Amazon EMR-Knoten nach der Bootstrap-Phase?

Erstellen Sie ein Bash-Skript, das dem folgenden ähnelt:

Hinweis:

  • Achten Sie darauf, s3://doc-example-bucket/Bootstraps/script_b.sh durch den Amazon Simple Storage Service (Amazon S3)-Pfad Ihrer Wahl zu ersetzen.
  • Achten Sie darauf, /home/hadoop/extrajars/* durch Ihren benutzerdefinierten JAR-Dateipfad zu ersetzen.
  • Stellen Sie sicher, dass die Amazon EMR-Ausführungsrolle über Berechtigungen für den Zugriff auf diesen S3-Bucket verfügt.
#!/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

Starten Sie den EMR-Cluster und fügen Sie eine Bootstrap-Aktion hinzu, die der folgenden ähnelt:

#!/bin/bash
pwd
aws s3 cp s3://doc-example-bucket/Bootstraps/script_b.sh .
chmod +x script_b.sh
nohup ./script_b.sh &

Für einen einzelnen Job

Verwenden Sie die Option --jars, um den benutzerdefinierten JAR-Pfad zu übergeben, wenn Sie spark-submit ausführen.

Beispiel:

spark-submit --deploy-mode client --class org.apache.spark.examples.SparkPi --master yarn spark-examples.jar 100 --jars /home/hadoop/extrajars/*

**Hinweis:**Um Klassenkonflikte zu vermeiden, fügen Sie keine Standard-JARs ein, wenn Sie die Option --jars verwenden. Fügen Sie beispielsweise spark-core.jar nicht ein, da es bereits im Cluster vorhanden ist.

Weitere Informationen zur Konfiguration von Klassifizierungen finden Sie unter Spark konfigurieren.


Verwandte Informationen

Spark-Konfiguration

Wie behebe ich den Fehler „Container wurde von YARN wegen Überschreitung der Speicherlimits getötet“ in Spark auf Amazon EMR?

AWS OFFICIAL
AWS OFFICIALAktualisiert vor 2 Jahren