Ошибка масштабирования задания с VerifyError в EMR версии 4.2.0
У нас есть работа Scalding, которую я хочу запустить на AWS Elastic MapReduce с использованием метки релиза 4.2.0.
Эта работа была успешно выполнена на AMI 2.4.2. Когда мы обновили его до AMI 3.7.0, мы столкнулись с java.lang.VerifyError
вызвано несовместимыми банками. Наш проект использует версию 1.5 библиотеки commons-codec, но более ранние несовместимые версии поставляются с AMI. Точно так же наш проект использует Scala 2.10, но версия 2.11 поставляется с AMI. Мы решили эту проблему, добавив скрипт начальной загрузки, чтобы удалить все файлы, соответствующие commons-codec-1.[234].jar
или же scala-library-2.11.*.jar
из кластера.
Теперь мы снова хотим обновить систему до 4.2.0 и снова получить VerifyError:
```Исключение в потоке"main" newInstance(DelegatingConstructorAccessorImpl.java:45) на java.lang.reflect.Constructor.newInstance(Constructor.java:526) на com.twitter.scalding.Job$.apply(Job.scala:47) на com.twitter.scalding.Tool.getJob(Tool.scala:48) в com.twitter.scalding.Tool.run(Tool.scala:68) в org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70) в com.snowplowanalytics.snowplow.enrich.hadoop.JobRunner$.main(JobRunner.scala:33) в com.snowplowanalytics.snowplow.enrich.hadoop.JobRunner.main(JobRunner.scala) в sun.reflect.NativeMethodAccessorImpl.invoke0(родной) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) в java.lang.reflect.Method.invoke(Method.java:606) в org.apache.hadoop.util.RunJar.run(RunJar.java:221) в org.apache.hadoop.util.RunJar.main(RunJar.java:136) Причина: java.lang.VerifyError: Неверный тип в стеке операндов Сведения об исключении: Местоположение: com/snowplowanalytics/snowplow/enrich/common/utils/ConversionUtils$.decodeBase64Url(Ljava/lang/String;Ljava/ языки /String;)Lscalaz/ проверки; @5: invokevirtual Причина: Тип 'org/apache/commons/codec/binary/Base64' (текущий кадр, стек [0]) нельзя назначить для 'org/apache/commons/codec/binary/BaseNCodec' Текущий кадр: bci: @5 flags: { } locals: { 'com/snowplowanalytics/snowplow/enrich/common/utils/ConversionUtils$', стек java / lang / String, java / lang / String: { 'org/apache/commons/ кодек / двоичный файл /Base64', 'java/lang/String' } Байт-код: 0000000: 2ab7 008a 2cb6 0090 3a04 bb00 5459 1904 0000010: b200 96b7 0099 3a05 b200 9e19 05b9 00a4 0000020: 0200 b900 aa01 00a 009e 4 009 009e 0000030: ac59 B200 4112 aeb6 00b1 B700 b4b2 0041 0000040: 06bd 0004 5903 2b53 5904 2c53 5905 2db6 0000050: 00b9 53b6 00bf B900 C502 00b9 00a4 0200 0000060: B900 C801 00b0 Исключение обработчика Таблица: BCI [0, 42] => обработчик: 42 Таблица стековых карт: same_locals_1_stack_item_frame(@42, объект [#182]) same_locals_1_stack_item_frame(@101, объект [#206]) в com.snowplowanalytics.snowplow.enrich.hadoop.EtlJobConfig$.com$snowplow $ $ Конфигурируйте $$base64ToJsonNode(EtlJobConfig.scala:224) в com.snowplowanalytics.snowplow.enrich.hadoop.EtlJobConfig$.loadConfigAndFilesToCache(EtlJobConfig.scala:126) в com.snowplowanalyens.lj.jlj.jl.jl.jp:139) ... еще 16 ```
Изучение, какие банки остаются в кластере после очистки:
$ sudo find / -name "*scala-*"
/usr/share/aws/emr/emrfs/cli/lib/scala-library-2.10.5.jar
/usr/share/aws/emr/emrfs/cli/lib/scala-reflect-2.10.4.jar
/usr/share/aws/emr/emrfs/cli/lib/scala-logging-api_2.10-2.1.2.jar
/usr/share/aws/emr/emrfs/cli/lib/nscala-time_2.10-1.2.0.jar
/usr/share/aws/emr/emrfs/cli/lib/scala-logging-slf4j_2.10-2.1.2.jar
$ sudo find / -name "*commons-codec*"
/usr/share/aws/emr/node-provisioner/lib/commons-codec-1.9.jar
/usr/share/aws/emr/emr-metrics/lib/commons-codec-1.6.jar
/usr/share/aws/emr/emr-metrics-client/lib/commons-codec-1.6.jar
/usr/share/aws/emr/emrfs/lib/commons-codec-1.9.jar
/usr/share/aws/emr/hadoop-state-pusher/lib/commons-codec-1.8.jar
/usr/lib/hbase/lib/commons-codec-1.7.jar
/usr/lib/mahout/lib/commons-codec-1.7.jar
Та же ошибка происходит с AMI 4.1.0. Что изменилось между 3.7.0 и 4.xx, что вызывает эту проблему, и что я могу сделать, чтобы исправить это?
1 ответ
В конце я добавил следующую логику на этапе начальной загрузки:
wget 'http://central.maven.org/maven2/commons-codec/commons-codec/1.5/commons-codec-1.5.jar'
sudo mkdir -p /usr/lib/hadoop/lib
sudo cp commons-codec-1.5.jar /usr/lib/hadoop/lib/remedial-commons-codec-1.5.jar
rm commons-codec-1.5.jar
Это загружает правильную версию фляги от Maven и помещает это в начало пути к классу для шага провала задания, где это имеет приоритет над другими версиями фляги.
Есть ли более чистое решение?