Saltar al contenido

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

4 minutos de lectura
0

Quiero resolver el error «java.lang.ClassNotFoundException» de Apache Spark en Amazon EMR.

Descripción corta

El error java.lang.ClassNotFoundException de Spark se produce por los siguientes motivos:

  • 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. Como resultado, el cargador de clases selecciona solo los archivos JAR que existen en la ubicación que has especificado en la configuración.

Resolución

Para resolver el error java.lang.ClassNotFoundException, comprueba el seguimiento de la pila para encontrar el nombre de la clase que falta. A continuación, agrega la ruta de tu JAR personalizado (que contiene la clase que falta) a la ruta de la clase Spark. Puedes agregar la ruta de tu JAR personalizado en un clúster en ejecución, en un clúster nuevo o al enviar un trabajo.

Adición de una ruta JAR personalizada a un clúster en ejecución

En /etc/spark/conf/spark-defaults.conf, agrega la ruta de tu JAR personalizado a los nombres de clase que se especifican en el seguimiento de la pila de errores.

Ejemplo:

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

Nota: Sustituye example-custom-jar-path por tu ruta JAR personalizada.

Adición de una ruta JAR personalizada a un nuevo clúster

Para agregar la ruta JAR personalizada a las rutas de clases existentes en /etc/spark/conf/spark-defaults.conf, proporciona un objeto de configuración al crear un clúster nuevo. Utiliza las versiones 5.14.0 o posteriores de Amazon EMR para crear un clúster nuevo.

Para Amazon EMR 5.14.0 a Amazon EMR 5.17.0, incluye 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, incluye /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, actualiza 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.36.0, actualiza 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/"
    }
  }
]

En las versiones 6.0.0 y posteriores de Amazon EMR, no puedes usar la configuración para actualizar la ruta JAR porque el archivo conf incluye varias rutas JAR. Además, la longitud de cada configuración de propiedades que actualices no puede superar los 1024 caracteres. Para pasar la ubicación JAR personalizada a spark-defaults.conf, agrega una acción de arranque. Para obtener más información, consulta ¿Cómo actualizo todos los nodos de Amazon EMR después de la acción de arranque?

Para agregar una acción de arranque, consulta Agregar acciones de arranque personalizadas y, a continuación, realiza las siguientes acciones:

  • Sustituye s3://example-bucket/Bootstraps/script_b.sh por tu ruta de Amazon Simple Storage Service (Amazon S3).
  • Asegúrate de sustituir /home/hadoop/extrajars/* por la ruta del archivo JAR personalizada.
  • Confirma que el rol de versión ejecutable de Amazon EMR tenga los permisos necesarios para acceder al bucket de Amazon S3.
    Nota: Cuando agregas el script de arranque, el script se aplica a la configuración de Spark del clúster en lugar de a un trabajo específico.

Ejemplo de script para cambiar /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 &

Nota: Sustituye example-bucket por tu bucket de Amazon S3.

Adición de ruta JAR personalizada al enviar un trabajo

Para agregar tu ruta JAR personalizada al enviar un trabajo, ejecuta el comando spark-submit con la opción jars. Para obtener más información, consulta Launching applications with spark-submit (Inicio de aplicaciones con el envío de Spark) en el sitio web de Apache Spark.

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

Nota: Sustituye example-custom-jar-path por tu ruta JAR personalizada. Para evitar conflictos de clases, no incluyas los JAR estándar al utilizar la opción jars. Por ejemplo, no incluyas spark-core.jar porque ya existe en el clúster. Para obtener más información, consulta Configurar Spark.

Información relacionada

Spark configuration (Configuración de Spark) en el sitio web de Apache Spark

¿Cómo puedo resolver el error «Container killed by YARN for exceeding memory limits» en Spark en Amazon EMR?

OFICIAL DE AWSActualizada hace un año