Come posso risolvere l’errore "java.lang.ClassNotFoundException" in Spark su Amazon EMR?

4 minuti di lettura
0

Quando utilizzo file JAR personalizzati in un lavoro spark-submit o PySpark su Amazon EMR, ricevo un errore java.lang.ClassNotFoundException.

Breve descrizione

Questo errore si verifica quando si verifica una delle seguenti condizioni:

  • Il lavoro spark-submit non riesce a trovare i file pertinenti nel percorso classe.
  • Un'azione bootstrap o una configurazione personalizzata sovrascrive i percorsi classe. Quando ciò accade, il class loader preleva solo i file JAR presenti nella posizione specificata nella configurazione.

Risoluzione

Controlla la traccia dello stack per trovare il nome della classe mancante. Quindi, aggiungi il percorso del tuo JAR personalizzato (contenente la classe mancante) al percorso classe Spark. Puoi eseguire questa operazione mentre il cluster è in esecuzione, quando avvii un nuovo cluster o quando inoltri un lavoro.

Su un cluster in esecuzione

In /etc/spark/conf/spark-defaults.conf, aggiungi il percorso del tuo JAR personalizzato ai nomi delle classi specificati nella traccia dello stack di errori. Nell'esempio seguente, /home/hadoop/extrajars/* è il percorso JAR personalizzato.

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/*

Su un nuovo cluster

Aggiungi il percorso JAR personalizzato ai percorsi classe esistenti in /etc/spark/conf/spark-defaults.conf fornendo un oggetto di configurazione quando crei un cluster.

Nota: Per utilizzare questa opzione, devi creare un cluster utilizzando la versione 5.14.0 o successiva di Amazon EMR.

Per Amazon EMR 5.14.0 fino ad Amazon EMR 5.17.0, includi quanto segue:

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

Per Amazon EMR 5.17.0 fino ad Amazon EMR 5.18.0, includi /usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar come percorso JAR aggiuntivo:

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

Per Amazon EMR 5.19.0 fino ad Amazon EMR 5.32.0, aggiorna il percorso JAR come segue:

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

Per Amazon EMR 5.33.0 fino ad Amazon EMR 5.34.0, aggiorna il percorso JAR come segue:

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

Per la versione 6.0.0 e successive di Amazon EMR, l'aggiornamento del percorso JAR tramite la configurazione non funziona. Con queste versioni, il file .conf include diversi percorsi di file jar. Inoltre, la lunghezza della configurazione per ogni proprietà che stai aggiornando non può essere superiore a 1.024 caratteri. Tuttavia, puoi aggiungere un'azione bootstrap per passare la posizione JAR personalizzata a spark-defaults.conf. Per ulteriori informazioni, consulta Come posso aggiornare tutti i nodi Amazon EMR dopo la fase di bootstrap?

Crea uno script bash simile al seguente:

Nota:

  • Assicurati di sostituire s3://doc-example-bucket/Bootstraps/script_b.sh con il percorso Amazon Simple Storage Service (Amazon S3) di tua scelta.
  • Assicurati di sostituire **/home/hadoop/extrajars/\ *** con il percorso del tuo file JAR personalizzato.
  • Assicurati che il ruolo di esecuzione di Amazon EMR disponga delle autorizzazioni per accedere a questo bucket S3.
#!/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

Avvia il cluster EMR e aggiungi un’azione di bootstrap simile alla seguente:

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

Per un solo lavoro

Usa l'opzione --jars per passare il percorso JAR personalizzato quando esegui spark-submit.

Esempio:

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

Nota: Per evitare conflitti di classe, non includere JAR standard quando usi l'opzione --jars. Ad esempio, non includere spark-core.jar perché esiste già nel cluster.

Per ulteriori informazioni sulla configurazione delle classificazioni, consulta Configura Spark.


Informazioni correlate

Configurazione Spark

Come posso risolvere l'errore "Container killed by YARN for exceeding memory limits" in Spark su Amazon EMR?

AWS UFFICIALE
AWS UFFICIALEAggiornata 2 anni fa