Direkt zum Inhalt

Wie behebe ich den Fehler „java.lang.ClassNotFoundException“ in Spark auf Amazon EMR?

Lesedauer: 4 Minute
0

Ich möchte den Fehler „java.lang.ClassNotFoundException“ in Apache Spark auf Amazon EMR beheben.

Kurzbeschreibung

Der Fehler java.lang.ClassNotFoundException in Spark tritt aus den folgenden Gründen auf:

  • Der spark-submit-Auftrag kann die relevanten Dateien im Klassenpfad nicht finden.
  • Eine Bootstrap-Aktion oder eine benutzerdefinierte Konfiguration überschreibt die Klassenpfade. Dadurch nimmt das Klassen-Ladeprogramm nur die JAR-Dateien auf, die an dem Speicherort vorhanden sind, den du in deiner Konfiguration angegeben hast.

Lösung

Um den Fehler java.lang.ClassNotFoundException zu beheben, überprüfe die Stack-Ablaufverfolgung, um den Namen der fehlenden Klasse zu finden. Füge dann den Pfad des benutzerdefinierten JAR (das die fehlende Klasse enthält) zum Spark-Klassenpfad hinzu. Du kannst den Pfad des benutzerdefinierten JAR in einem aktuell ausgeführten Cluster, einem neuen Cluster oder beim Absenden eines Auftrags hinzufügen.

Den benutzerdefinierten JAR-Pfad zu einem laufenden Cluster hinzufügen

Füge in /etc/spark/conf/spark-defaults.conf den Pfad des benutzerdefinierten JAR an die Klassennamen an, die in der Fehler-Stack-Ablaufverfolgung angegeben sind.

Beispiel:

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

Hinweis: Ersetze example-custom-jar-path durch deinen benutzerdefinierten JAR-Pfad.

Den benutzerdefinierten JAR-Pfad zu einem neuen Cluster hinzufügen

Wenn du einen neuen Cluster erstellst, gib ein Konfigurationsobjekt an, um den benutzerdefinierten JAR-Pfad zu vorhandenen Klassenpfaden in /etc/spark/conf/spark-defaults.conf hinzuzufügen. Verwende Amazon-EMR-Versionen 5.14.0 oder höher, um einen neuen Cluster zu erstellen.

Füge 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/*"
    }
  }
]

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

Aktualisiere für Amazon EMR 5.19.0 auf Amazon EMR 5.32.0 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/*"
    }
  }
]

Aktualisiere für Amazon EMR 5.33.0 auf Amazon EMR 5.36.0 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-Versionen 6.0.0 und höher kannst du die Konfiguration nicht verwenden, um den JAR-Pfad zu aktualisieren, da die conf-Datei mehrere JAR-Pfade enthält. Außerdem darf die Länge jeder Eigenschaftskonfiguration, die du aktualisierst, 1024 Zeichen nicht überschreiten. Füge eine Bootstrap-Aktion hinzu, um den benutzerdefinierten JAR-Speicherort an spark-defaults.conf weiterzugeben. Weitere Informationen findest du unter Wie aktualisiere ich alle Amazon-EMR-Knoten nach der Bootstrap-Phase?

Informationen zum Hinzufügen einer Bootstrap-Aktion findest du unter Hinzufügen benutzerdefinierter Bootstrap-Aktionen. Führe dann die folgenden Aktionen aus:

  • Ersetze s3://example-bucket/Bootstraps/script_b.sh durch deinen Amazon Simple Storage Service (Amazon S3)-Pfad.
  • Ersetze /home/hadoop/extrajars/* durch deinen benutzerdefinierten JAR-Dateipfad.
  • Vergewissere dich, dass die Amazon-EMR-Laufzeitrolle über die erforderlichen Berechtigungen für den Zugriff auf den Amazon-S3-Bucket verfügt.
    Hinweis: Wenn du das Bootstrap-Skript hinzufügst, gilt das Skript für die Spark-Konfiguration des Clusters und nicht für einen bestimmten Auftrag.

Beispiel-Skript zum Ändern von /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 &

Hinweis: Ersetze example-bucket durch deinen Amazon-S3-Bucket.

Den benutzerdefinierten JAR-Pfad beim Absenden eines Auftrags hinzufügen

Um den benutzerdefinierten JAR-Pfad hinzuzufügen, wenn du einen Auftrag absendest, führe den Befehl spark-submit mit der Option jars aus. Weitere Informationen findest du unter Launching applications with spark-submit (Starten von Anwendungen mit spark-submit) auf der Apache-Spark-Website.

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

Hinweis: Ersetze example-custom-jar-path durch deinen benutzerdefinierten JAR-Pfad. Um Klassenkonflikte zu vermeiden, beziehe keine Standard-JARs ein, wenn du die Option jars verwendest. Beziehe beispielsweise spark-core.jar nicht ein, da es bereits im Cluster vorhanden ist. Weitere Informationen findest du unter Spark konfigurieren.

Ähnliche Informationen

Spark configuration (Spark-Konfiguration) auf der Apache Spark-Website

Wie behebe ich den Fehler „Container killed by YARN for exceeding memory limits“ in Spark auf Amazon EMR?

AWS OFFICIALAktualisiert vor einem Jahr