Ошибка авро на AWS EMR
Я использую spark-redshift ( https://github.com/databricks/spark-redshift), который использует avro для передачи.
Чтение из Redshift в порядке, во время записи я получаю
Caused by: java.lang.NoSuchMethodError: org.apache.avro.generic.GenericData.createDatumWriter(Lorg/apache/avro/Schema;)Lorg/apache/avro/io/DatumWriter
попытался использовать Amazon EMR 4.1.0 (Spark 1.5.0) и 4.0.0 (Spark 1.4.1). Не могу сделать
import org.apache.avro.generic.GenericData.createDatumWriter
либо просто
import org.apache.avro.generic.GenericData
Я использую оболочку scala. Попробовал загрузить несколько других файлов avro-mapred и avro, попробовал установить
{"classification":"mapred-site","properties":{"mapreduce.job.user.classpath.first":"true"}},{"classification":"spark-env","properties":{"spark.executor.userClassPathFirst":"true","spark.driver.userClassPathFirst":"true"}}
и добавление этих банок к искровой classpath. Возможно, нужно как-то настроить Hadoop (EMR).
Это звонит кому-нибудь?
4 ответа
Просто для справки - обходной путь Алексея Настецкого
удалить банки из мастер-узла
find / -name "*avro*jar" 2> /dev/null -print0 | xargs -0 -I file sudo rm file
удалить банки из подчиненных узлов
yarn node -list | sed 's/ .*//g' | tail -n +3 | sed 's/:.*//g' | xargs -I node ssh node "find / -name "*avro*jar" 2> /dev/null -print0 | xargs -0 -I file sudo rm file
Правильная настройка конфигов, предложенная Джонатаном, тоже стоит того.
spark-redshift
сопровождающий здесь.
Другие пользователи EMR сталкивались с подобными ошибками при использовании более новых версий spark-avro
библиотека (которая spark-redshift
зависит от). В двух словах, проблема заключается в том, что более старая версия Avro EMR имеет приоритет перед новой версией, требуемой spark-avro
, На https://github.com/databricks/spark-avro/issues/91 проблеме, которая, по-видимому, соответствует исключению, о котором здесь сообщалось, один пользователь предложил встроить JAR-файлы Avro с кодом своего приложения: https://github.com/databricks/spark-avro/issues/91
Джонатан из EMR здесь. Частично проблема заключается в том, что Hadoop зависит от Avro 1.7.4, а полный путь к классу Hadoop включен в путь Spark в EMR. Это может помочь нам обновить зависимость Hadoop Avro до 1.7.7, чтобы она соответствовала зависимости Spark Avro, хотя я немного боюсь, что это может сломать что-то еще, но я все равно могу попробовать.
Кстати, одна проблема, которую я заметил с вашим примером конфигурации кластера EMR, заключается в том, что вы используете классификацию конфигурации "spark-env", тогда как классификация "spark-defaults" была бы подходящей для настройки spark.{Driver,executor}.userClassPathFirst. Я не уверен, что это само по себе решит вашу проблему.
Ошибка конфликта времени выполнения в EMR, связанная с Avro, очень распространена. Avro широко используется, и многие банки имеют его в качестве зависимости. Я видел несколько вариантов этого вопроса с другим методом в "NoSuchMethodError" или в разных версиях Avro.
Я не смог решить это с флагом 'spark.executor.userClassPathFirst', потому что я получил LinkageError.
Вот решение, которое решило конфликт для меня:
- Используйте IntelliJ Dependancy Analyzer (плагин Maven), чтобы исключить Avro из всех зависимостей, которые вызывают конфликт.
При настройке EMR добавьте действие начальной загрузки, которое вызывает скрипт bash, который загружает конкретный JAR Avro:
#!/bin/bash
mkdir -p /home/hadoop/lib/ cd /home/hadoop/lib/ wget http://apache.spd.co.il/avro/avro-1.8.0/java/avro-1.8.0.jar
При настройке EMR добавьте следующую конфигурацию:
[ {"classification":"spark-defaults", "properties":{ "spark.driver.extraLibraryPath":"/home/hadoop/lib/avro-1.8.0.jar:/usr/lib/hadoop/*:/usr/lib/hadoop/../hadoop-hdfs/*:/usr/lib/hadoop/../hadoop-mapreduce/*:/usr/lib/hadoop/../hadoop-yarn/*:/etc/hive/conf:/usr/lib/hadoop/../hadoop-lzo/lib/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*", "spark.executor.extraClassPath":"/home/hadoop/lib/avro-1.8.0.jar:/usr/lib/hadoop/*:/usr/lib/hadoop/../hadoop-hdfs/*:/usr/lib/hadoop/../hadoop-mapreduce/*:/usr/lib/hadoop/../hadoop-yarn/*:/etc/hive/conf:/usr/lib/hadoop/../hadoop-lzo/lib/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*", "spark.driver.extraClassPath":"/home/hadoop/lib/avro-1.8.0.jar:/usr/lib/hadoop/*:/usr/lib/hadoop/../hadoop-hdfs/*:/usr/lib/hadoop/../hadoop-mapreduce/*:/usr/lib/hadoop/../hadoop-yarn/*:/etc/hive/conf:/usr/lib/hadoop/../hadoop-lzo/lib/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*"}, "configurations":[]} ]
Как видите, мне пришлось добавить мою новую библиотеку с существующими библиотеками. Это не сработало иначе.