Использование typeafe config с Spark on Yarn

У меня есть задание Spark, которое считывает данные из файла конфигурации. Этот файл представляет собой безопасный конфигурационный файл.

Код, который читает конфиг, выглядит так:

ConfigFactory.load().getConfig("com.mycompany")

Теперь я не собираю application.conf как часть моего uber jar, так как я хочу передать файл как внешний файл.

Содержимое внешнего файла application.conf, который я хочу использовать, выглядит следующим образом:

com.mycompany {
  //configurations my program needs
}

Этот файл application.conf существует в файловой системе моего локального компьютера (а не в HDFS)

Я использую Spark 1.6.1 с Yarn

Вот как выглядит моя команда spark-submit:

LOG4J_FULL_PATH=/log4j-path
ROOT_DIR=/application.conf-path

    /opt/deploy/spark/bin/spark-submit \
    --class com.mycompany.Main \
    --master yarn \
    --deploy-mode cluster \
    --files $ROOT_DIR/application.conf \
    --files $LOG4J_FULL_PATH/log4j.xml \
    --conf spark.executor.extraClassPath="-Dconfig.file=file:application.conf" \
    --driver-class-path $ROOT_DIR/application.conf \
    --verbose \
    /opt/deploy/lal-ml.jar

Я получаю следующее исключение:

2016-11-09 12:32:14 ERROR ApplicationMaster:95 - User class threw exception: com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'com'
com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'com'
    at com.typesafe.config.impl.SimpleConfig.findKey(SimpleConfig.java:124)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:147)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:159)
    at com.typesafe.config.impl.SimpleConfig.find(SimpleConfig.java:164)
    at com.typesafe.config.impl.SimpleConfig.getObject(SimpleConfig.java:218)
    at com.typesafe.config.impl.SimpleConfig.getConfig(SimpleConfig.java:224)
    at com.typesafe.config.impl.SimpleConfig.getConfig(SimpleConfig.java:33)
    at com.mycompany.Main$.main(Main.scala:36)
    at com.mycompany.Main.main(Main.scala)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.spark.deploy.yarn.ApplicationMaster$$anon$2.run(ApplicationMaster.scala:542)

Итак, мой вопрос: кто-нибудь знает, как я могу загрузить внешний файл typeafe application.conf, который находится на моем локальном компьютере, с помощью spark-submit и yarn?

Я пробовал следовать некоторым решениям в Как добавить безопасный для типов файл конфигурации, расположенный в HDFS, в spark-submit (режим кластера)? и в Типичная конфигурация в Spark, а также в Как передать параметр -D или переменную среды в задание Spark? и ничего не получилось

Я буду признателен за любое направление решения этой проблемы

заранее спасибо


person Gideon    schedule 09.11.2016    source источник


Ответы (2)


Итак, немного покопавшись в исходном коде Spark 1.6.1, я нашел решение.

Вот шаги, которые вам необходимо предпринять, чтобы получить как log4j, так и application.conf, используемые вашим приложением при отправке в yarn в режиме кластера:

  • При передаче нескольких файлов, например, при передаче файлов application.conf и log4j.xml, вам необходимо отправить их, используя только одну строку, например: --files "$ROOT_DIR/application.conf,$LOG4J_FULL_PATH/log4j.xml" (разделите их запятыми)
  • Это все для application.conf. Нет необходимости в extraJavaOpts для application.conf (как было написано в моем вопросе). Проблема в том, что Spark использовал только последний переданный аргумент --files, и поэтому передавался log4j. Чтобы использовать log4j.xml, мне также пришлось сделать следующий шаг
  • Добавьте еще одну строку в отправку искры следующим образом: --conf spark.driver.extraJavaOptions="-Dlog4j.configuration=file:log4j.xml" - обратите внимание, что как только вы передадите ее с помощью --files, вы можете просто сослаться на имя файла без какого-либо пути

Примечание: я не пробовал, но из того, что я видел, если вы пытаетесь запустить его в клиентском режиме, я думаю, что строку spark.driver.extraJavaOptions следует переименовать во что-то вроде driver-java-options Вот и все. Так просто, и я бы хотел, чтобы эти вещи были лучше задокументированы. Надеюсь, этот ответ кому-то поможет

Ваше здоровье

person Gideon    schedule 14.11.2016
comment
Вы должны иметь возможность использовать список файлов, разделенных запятыми, для --files вместо того, чтобы указывать флаг несколько раз. - person vpipkt; 13.01.2017
comment
Ага, это именно то, чем я закончил - person Gideon; 13.01.2017
comment
--driver-java-options='-Dmy.config.path=myConfigValue' из другого ответа - person ruhong; 30.06.2017

Несмотря на то, что это вопрос год назад, у меня была аналогичная проблема с ConfigFactor. Чтобы иметь возможность читать application.conf файл, вам нужно сделать две вещи.

  • Отправьте файл водителю. Это делается с помощью следующего кода --files /path/to/file/application.conf. Обратите внимание, что вы можете прочитать его из HDFS, если хотите.
  • Отправьте пакет com.typesafe.config. Это делается с помощью --packages com.typesafe:config:version.

Поскольку файл application.conf будет находиться в том же временном каталоге, что и основное приложение jar, вы можете предположить в своем коде.

Используя приведенный выше ответ (https://stackoverflow.com/a/40586476/6615465), код для этого вопроса будет следующее:

LOG4J_FULL_PATH=/log4j-path
ROOT_DIR=/application.conf-path

/opt/deploy/spark/bin/spark-submit \
--packages com.typesafe:config:1.3.2
--class com.mycompany.Main \
--master yarn \
--deploy-mode cluster \
--files "$ROOT_DIR/application.conf, $LOG4J_FULL_PATH/log4j.xml" \
--conf spark.executor.extraClassPath="-Dconfig.file=file:application.conf" \
--driver-class-path $ROOT_DIR/application.conf \
--verbose \
/opt/deploy/lal-ml.jar
person Antonio Méndez    schedule 15.05.2018
comment
Обратите внимание, что в приведенном выше фрагменте кода есть опечатка - в первой строке отсутствует буква «L» из LOG4J_FULL_PATH. Я не могу редактировать ответ, так как это всего лишь редактирование одного символа - должно быть не менее 6, чтобы его можно было принять как правку! - person Anthony K; 22.01.2019