Como resolvo o erro “java.lang.ClassNotFoundException” do Spark no Amazon EMR?

4 minuto de leitura
0

Quando uso arquivos JAR personalizados em um trabalho spark-submit ou PySpark no Amazon EMR, recebo um erro java.lang.ClassNotFoundException.

Descrição breve

Esse erro ocorre quando uma das seguintes condições é verdadeira:

  • O trabalho spark-submit não consegue encontrar os arquivos relevantes no caminho da classe.
  • Uma ação de bootstrap ou configuração personalizada está substituindo os caminhos da classe. Quando isso acontece, o carregador de classes coleta somente os arquivos JAR que existem no local que você especificou na sua configuração.

Resolução

Verifique o rastreamento da pilha para encontrar o nome da classe ausente. Em seguida, adicione o caminho do seu JAR personalizado (contendo a classe ausente) ao caminho da classe Spark. Você pode fazer isso enquanto o cluster está em execução, ao iniciar um novo cluster ou ao enviar um trabalho.

Em um cluster em execução

Em /etc/spark/conf/spark-defaults.conf, anexe o caminho do seu JAR personalizado aos nomes das classes especificados no rastreamento da pilha de erros. No exemplo a seguir, /home/hadoop/extrajars/* é o caminho JAR personalizado.

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

Em um novo cluster

Anexe o caminho JAR personalizado aos caminhos de classe existentes em /etc/spark/conf/spark-defaults.conf, fornecendo um objeto de configuração ao criar um cluster.

**Observação:**para usar essa opção, você deve criar um cluster usando a versão 5.14.0 ou posterior do Amazon EMR.

Para o Amazon EMR 5.14.0 ao Amazon EMR 5.17.0, inclua o seguinte:

[
  {
    "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 o Amazon EMR 5.17.0 ao Amazon EMR 5.18.0, inclua /usr/share/aws/emr/s3select/lib/emr-s3-select-spark-connector.jar como o caminho 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 o Amazon EMR 5.19.0 ao Amazon EMR 5.32.0, atualize o caminho do JAR, da seguinte forma:

[
  {
    "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 o Amazon EMR 5.33.0 ao Amazon EMR 5.34.0, atualize o caminho do JAR, da seguinte forma:

[
  {
    "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 a versão 6.0.0 e posterior do Amazon EMR, não adianta atualizar o caminho do JAR usando a configuração. Com essas versões, o arquivo .conf inclui vários caminhos de arquivo jar. Além disso, o tamanho da configuração de cada propriedade que você está atualizando não pode ultrapassar 1024 caracteres. No entanto, você pode adicionar uma ação de bootstrap para passar a localização personalizada do JAR para spark-defaults.conf. Para mais informações, consulte Como faço para atualizar todos os nós do Amazon EMR após a fase de bootstrap?

Crie um script bash semelhante ao seguinte:

Observação:

  • certifique-se de substituir s3://doc-example-bucket/Bootstraps/script_b.sh pelo caminho do Amazon Simple Storage Service (Amazon S3) de sua escolha.
  • Certifique-se de substituir /home/hadoop/extrajars/* pelo caminho do arquivo JAR personalizado.
  • Certifique-se de que a função de execução do Amazon EMR tenha permissões para acessar esse bucket do 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 o cluster do EMR e adicione uma ação de bootstrap semelhante à seguinte:

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

Para um único trabalho

Use a opção --jars para transmitir o caminho JAR personalizado ao executar spark-submit.

Exemplo:

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

Observação: para evitar conflitos de classe, não inclua JARs padrão ao usar a opção --jars. Por exemplo, não inclua spark-core.jar porque ele já existe no cluster.

Para obter mais informações sobre como configurar classificações, consulte Configurar o Spark.


Informações relacionadas

Configuração do Spark

Como resolvo o erro “Contêiner eliminado pelo YARN por exceder os limites de memória” do Spark no Amazon EMR?

AWS OFICIAL
AWS OFICIALAtualizada há 2 anos