¿Cómo puedo solucionar el error «java.lang.classNotFoundException» de Spark en Amazon EMR?

4 minutos de lectura
0

Al usar archivos JAR personalizados en un trabajo de spark-submit o PySpark en Amazon EMR, me sale el error java.lang.ClassNotFoundException.

Descripción corta

Este error aparece si se cumple una de las siguientes condiciones:

  • El trabajo spark-submit no encuentra archivos relevantes en la ruta de clases.
  • Una acción de arranque o una configuración personalizada anula las rutas de clases. Cuando esto ocurre, el cargador de clases selecciona solo los archivos JAR que existen en la ubicación que has especificado en la configuración.

Resolución

Compruebe el rastreo de la pila para encontrar el nombre de la clase que falta. A continuación, añada la ruta de su JAR personalizado (que contiene la clase que falta) a la ruta de la clase Spark. Puede hacerlo mientras el clúster se está ejecutando, al lanzar un nuevo clúster o al enviar un trabajo.

En un clúster en ejecución

En /etc/spark/conf/spark-defaults.conf, añada la ruta de su JAR personalizado a los nombres de clase que se especifican en el rastreo de la pila de errores. En el siguiente ejemplo, /home/hadoop/extrajars/* es la ruta de los JAR personalizados.

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

En un clúster nuevo

Añada la ruta JAR personalizada a las rutas de clases existentes en /etc/spark/conf/spark-defaults.conf proporcionando un objeto de configuración al crear un clúster.

Nota: Para utilizar esta opción, debe crear un clúster con la versión 5.14.0 o posterior de Amazon EMR.

Para Amazon EMR 5.14.0 a Amazon EMR 5.17.0, incluya lo siguiente:

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

Para Amazon EMR 5.17.0 a Amazon EMR 5.18.0, incluya /usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar como ruta JAR adicional:

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

Para Amazon EMR 5.19.0 a Amazon EMR 5.32.0, actualice la ruta JAR de la siguiente manera:

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

Para Amazon EMR 5.33.0 a Amazon EMR 5.34.0, actualice la ruta JAR de la siguiente manera:

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

Para la versión 6.0.0 y versiones posteriores de Amazon EMR, la actualización de la ruta JAR mediante la configuración no funciona. En estas versiones, el archivo.conf incluye varias rutas de archivos jar. Además, la longitud de la configuración de cada propiedad que está actualizando no puede superar los 1024 caracteres. Sin embargo, puede añadir una acción de arranque para pasar la ubicación JAR personalizada a spark-defaults.conf. Para obtener más información, consulte How do I update all Amazon EMR nodes after the bootstrap phase?

Cree un script bash similar al siguiente:

Nota:

  • Asegúrese de reemplazar s3://doc-example-bucket/Bootstraps/script_b.sh por la ruta de Amazon Simple Storage Service (Amazon S3) que elija.
  • Asegúrese de reemplazar /home/hadoop/extrajars/* por la ruta del archivo JAR personalizada.
  • Asegúrese de que el rol de ejecución de Amazon EMR tenga permisos para acceder a este bucket de 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

Inicie el clúster de EMR y añada una acción de arranque similar a la siguiente:

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

Para un solo trabajo

Use la opción --jars para pasar la ruta JAR personalizada cuando ejecute spark-submit.

Ejemplo:

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

Nota: Para evitar conflictos de clases, no incluya los JAR estándar al utilizar la opción --jars. Por ejemplo, no incluya spark-core.jar porque ya existe en el clúster.

Para obtener más información sobre cómo configurar clasificaciones, consulte Configure Spark.


Información relacionada

Spark configuration

How do I resolve the error "Container killed by YARN for exceeding memory limits" in Spark on Amazon EMR?

OFICIAL DE AWS
OFICIAL DE AWSActualizada hace 2 años