Добавить баночки в Spark Job - spark-submit

158

Правда ... это обсуждалось довольно много.

Однако есть много двусмысленности и некоторые ответы предоставлены ... включая дублирование ссылок на jar в конфигурации или опциях jars / executor / driver.

Двусмысленные и / или опущенные детали

Следуя двусмысленности, неясные и / или пропущенные детали должны быть разъяснены для каждого варианта:

  • Как влияет ClassPath
    • Водитель
    • Исполнитель (для выполнения задач)
    • Обе
    • не за что
  • Разделительный символ: запятая, двоеточие, точка с запятой
  • Если предоставленные файлы автоматически распространяются
    • для задач (каждому исполнителю)
    • для удаленного драйвера (если работает в режиме кластера)
  • Тип принятого URI: локальный файл, hdfs, http и т. д.
  • Если это место скопировано в общую папку (hdfs, local?)

Варианты, на которые это влияет:

  1. --jars
  2. SparkContext.addJar(...) метод
  3. SparkContext.addFile(...) метод
  4. --conf spark.driver.extraClassPath=... или --driver-class-path ...
  5. --conf spark.driver.extraLibraryPath=..., или --driver-library-path ...
  6. --conf spark.executor.extraClassPath=...
  7. --conf spark.executor.extraLibraryPath=...
  8. не стоит забывать, что последний параметр spark-submit также является файлом .jar.

Я знаю, где можно найти основную документацию по искрам , в частности, о том, как отправить , доступные параметры , а также JavaDoc . Тем не менее, это оставило для меня еще несколько пробелов, хотя и частично ответил.

Я надеюсь, что это не все так сложно, и что кто-то может дать мне четкий и краткий ответ.

Если бы я был догадаться из документации, кажется , что --jarsи SparkContext addJarи addFileметоды являются те , которые будут автоматически распространять файлы, в то время как другие варианты просто изменить CLASSPATH.

Можно ли предположить, что для простоты я могу добавить дополнительные файлы jar приложения, используя 3 основных параметра одновременно:

spark-submit --jar additional1.jar,additional2.jar \
  --driver-library-path additional1.jar:additional2.jar \
  --conf spark.executor.extraLibraryPath=additional1.jar:additional2.jar \
  --class MyClass main-application.jar

Нашел симпатичную статью по ответу на другой пост . Однако ничего нового не узнал. Постер хорошо отмечает разницу между локальным драйвером (клиент-пряжа) и удаленным драйвером (кластер пряжи). Определенно важно иметь в виду.

Йо Йо
источник
1
Под каким кластерным менеджером вы работаете? Standalone / ПРЯЖА / Mesos?
Ювал Ицчаков
Любой. Я намерен это как пояснение к оригинальной документации. В основном я использую автономный кластер, один экземпляр, клиент-пряжу, кластер пряжи. Другие могут использовать Mesos. Похоже, вы сделали несколько оригинальных исследований в своем блоге . В итоге я сделал то же самое, что и вы - используя шейдер для создания Uber JAR, чтобы упростить процесс развертывания.
YoYo
1
Я опубликую ответ о том, как мы развернем Spark Standalone, это может прояснить несколько вещей.
Ювал Ицчаков
6
Я приложил усилия, чтобы ответить на все ваши вопросы. Надеюсь, это поможет :)
Ювал Ицчаков
@Yuval Ицхаков, как упоминал Йойо, я также использую затененную банку, чтобы связать все мои зависимости, например, case-классы и другие фляги, которые я могу использовать. Я пытаюсь понять, когда я столкнусь с ситуацией, когда мне понадобятся несколько банок. Я имею в виду, я всегда могу связать эти несколько банок в 1 банку убер. Почему я не могу продолжать жить со своими затененными банками, связывающими все мои зависимости?
Шил Панчоли

Ответы:

177

ClassPath:

ClassPath зависит от того, что вы предоставляете. Есть несколько способов установить что-то на пути к классам:

  • spark.driver.extraClassPathили это псевдоним --driver-class-pathдля установки дополнительных путей к классам на узле, на котором работает драйвер.
  • spark.executor.extraClassPath установить дополнительный путь к классу на узлах Worker.

Если вы хотите, чтобы определенный JAR-файл был применен как к основному устройству, так и к рабочему, вы должны указать их отдельно в обоих флагах.

Разделительный характер:

Следуя тем же правилам, что и JVM :

  • Linux: двоеточие :
    • например: --conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar:/opt/prog/aws-java-sdk-1.10.50.jar"
  • Windows: точка с запятой ;
    • например: --conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar;/opt/prog/aws-java-sdk-1.10.50.jar"

Распределение файлов:

Это зависит от режима, в котором вы выполняете свою работу:

  1. Режим клиента - Spark запускает HTTP-сервер Netty, который при запуске распределяет файлы для каждого из рабочих узлов. Вы можете видеть, что когда вы начинаете свою работу в Spark:

    16/05/08 17:29:12 INFO HttpFileServer: HTTP File server directory is /tmp/spark-48911afa-db63-4ffc-a298-015e8b96bc55/httpd-84ae312b-5863-4f4c-a1ea-537bfca2bc2b
    16/05/08 17:29:12 INFO HttpServer: Starting HTTP Server
    16/05/08 17:29:12 INFO Utils: Successfully started service 'HTTP file server' on port 58922.
    16/05/08 17:29:12 INFO SparkContext: Added JAR /opt/foo.jar at http://***:58922/jars/com.mycode.jar with timestamp 1462728552732
    16/05/08 17:29:12 INFO SparkContext: Added JAR /opt/aws-java-sdk-1.10.50.jar at http://***:58922/jars/aws-java-sdk-1.10.50.jar with timestamp 1462728552767
  2. Режим кластера - в режиме кластера искра выбрала рабочий узел-лидер для выполнения процесса драйвера. Это означает, что задание не запускается напрямую с главного узла. Здесь Spark не будет устанавливать HTTP-сервер. Вы должны вручную сделать JARS доступным для всех рабочих узлов через HDFS / S3 / Другие источники, доступные для всех узлов.

Принятые URI для файлов

В разделе «Отправка приложений» документация Spark хорошо объясняет принятые префиксы для файлов:

При использовании spark-submit jar приложения вместе со всеми jar-файлами, включенными в опцию --jars, будет автоматически перенесен в кластер. Spark использует следующую схему URL, чтобы разрешить разные стратегии распространения jar-файлов:

  • file: - Абсолютные пути и file: / URI обслуживаются файловым сервером HTTP драйвера, и каждый исполнитель извлекает файл с HTTP-сервера драйвера.
  • hdfs :, http :, https :, ftp: - эти файлы и файлы JAR из URI, как и ожидалось
  • local: - ожидается, что URI, начинающийся с local: /, будет существовать как локальный файл на каждом рабочем узле. Это означает, что никакого сетевого ввода-вывода не будет, и он хорошо работает для больших файлов / JAR-файлов, которые передаются каждому работнику или совместно используются через NFS, GlusterFS и т. Д.

Обратите внимание, что файлы JAR и файлы копируются в рабочий каталог для каждого SparkContext на узлах исполнителя.

Как уже отмечалось, JAR-файлы копируются в рабочий каталог для каждого рабочего узла. Где именно это? Это , как правило , под /var/run/spark/work, вы их увидите , как это:

drwxr-xr-x    3 spark spark   4096 May 15 06:16 app-20160515061614-0027
drwxr-xr-x    3 spark spark   4096 May 15 07:04 app-20160515070442-0028
drwxr-xr-x    3 spark spark   4096 May 15 07:18 app-20160515071819-0029
drwxr-xr-x    3 spark spark   4096 May 15 07:38 app-20160515073852-0030
drwxr-xr-x    3 spark spark   4096 May 15 08:13 app-20160515081350-0031
drwxr-xr-x    3 spark spark   4096 May 18 17:20 app-20160518172020-0032
drwxr-xr-x    3 spark spark   4096 May 18 17:20 app-20160518172045-0033

И когда вы загляните внутрь, вы увидите все файлы JAR, на которых вы развернули:

[*@*]$ cd /var/run/spark/work/app-20160508173423-0014/1/
[*@*]$ ll
total 89988
-rwxr-xr-x 1 spark spark   801117 May  8 17:34 awscala_2.10-0.5.5.jar
-rwxr-xr-x 1 spark spark 29558264 May  8 17:34 aws-java-sdk-1.10.50.jar
-rwxr-xr-x 1 spark spark 59466931 May  8 17:34 com.mycode.code.jar
-rwxr-xr-x 1 spark spark  2308517 May  8 17:34 guava-19.0.jar
-rw-r--r-- 1 spark spark      457 May  8 17:34 stderr
-rw-r--r-- 1 spark spark        0 May  8 17:34 stdout

Затронутые варианты:

Самая важная вещь для понимания - это приоритет . Если вы передадите какое-либо свойство через код, оно будет иметь приоритет над любым параметром, указанным вами через spark-submit. Это упоминается в документации Spark:

Любые значения, указанные как флаги или в файле свойств, будут переданы приложению и объединены со значениями, указанными через SparkConf. Свойства, установленные непосредственно в SparkConf, имеют наивысший приоритет , затем флаги передаются в spark-submit или spark-shell, затем параметры в файле spark-defaults.conf

Поэтому убедитесь, что вы установили эти значения в нужных местах, чтобы не удивляться, когда один из них имеет приоритет над другим.

Давайте проанализируем каждый рассматриваемый вариант:

  • --jarsvs SparkContext.addJar: они идентичны, только один устанавливается с помощью spark submit и один через код. Выберите тот, который подходит вам лучше. Важно отметить, что использование любого из этих параметров не добавляет JAR в ваш путь к классу драйвера / исполнителя , вам нужно явно добавить их, используя extraClassPathконфигурацию обоих.
  • SparkContext.addJarvs SparkContext.addFile: используйте первый, когда у вас есть зависимость, которую необходимо использовать с вашим кодом. Используйте последнее, когда вы просто хотите передать произвольный файл своим рабочим узлам, что не является зависимостью времени выполнения в вашем коде.
  • --conf spark.driver.extraClassPath=...или --driver-class-path: это псевдонимы, не важно, какой вы выберете
  • --conf spark.driver.extraLibraryPath=..., or --driver-library-path ... То же, что и выше, псевдонимы.
  • --conf spark.executor.extraClassPath=...Используйте это, если у вас есть зависимость, которую нельзя включить в UAR JAR (например, из-за конфликтов времени компиляции между версиями библиотеки) и которую необходимо загрузить во время выполнения.
  • --conf spark.executor.extraLibraryPath=...Это передается как java.library.pathопция для JVM. Используйте это, когда вам нужен путь к библиотеке, видимый для JVM.

Можно ли предположить, что для простоты я могу добавить дополнительные файлы jar приложения, используя 3 основных параметра одновременно:

Вы можете смело предполагать это только для режима клиента, а не режима кластера. Как я уже говорил. Кроме того, приведенный вами пример имеет несколько избыточных аргументов. Например, передача JAR-файлов --driver-library-pathбесполезна, вам нужно передать их, extraClassPathесли вы хотите, чтобы они были на вашем пути к классам. В конечном счете, то, что вы хотите сделать при развертывании внешних JAR-файлов как на драйвере, так и на рабочем месте, это:

spark-submit --jars additional1.jar,additional2.jar \
  --driver-class-path additional1.jar:additional2.jar \
  --conf spark.executor.extraClassPath=additional1.jar:additional2.jar \
  --class MyClass main-application.jar
Ювал Ицчаков
источник
4
Отличный и исчерпывающий ответ. Спасибо. Не могли бы вы также рассказать больше о передовых методах развертывания с использованием Uber JAR в сравнении с зависимостями вне JAR (библиотеки во внешней папке и перечислены в MANIFEST.MFфайле)?
jsosnowski
2
@jsosnowski Обычно я обращаюсь к использованию внешних jar-файлов только тогда, когда есть конфликты, которые очень сложно решить с помощью моего Uber JAR-файла. Я обычно просто использую SBT assemblyMergeStrategyи выбираю классы, которые мне нужны, если возникают конфликты. Я бы вообще рекомендовал то же самое.
Ювал Ицчаков
9
@ yuval-itzchakov Спасибо за отличный ответ, очень полезно. Я хотел бы подчеркнуть один момент, чтобы помочь другим, которые, возможно, совершили ту же ошибку, что и я. Аргумент --jars переносит файлы jar только на каждую машину в кластере. Это НЕ говорит искре использовать их в поиске пути класса. --Driver-class-path (или аналогичные аргументы или параметры конфигурации) также требуются. Сначала я думал, что это были альтернативные способы сделать то же самое.
Тим Райан
1
@TimRyan Определенно. Если вы посмотрите на последнюю часть ответа, я передаю jar как --jarsфлагу, так и пути к классу драйвера / исполнителя.
Юваль Ицчаков
1
В конце концов я нашел, какzeppelin-env.sh добавить переменные окружения в и добавить --jarsв SPARK_SUBMIT_OPTIONS. Это сработало. URI использование формата I является --jars=local:///mnt/dir/file.jar.
Майк
4

Другой подход spark 2.1.0заключается в использовании --conf spark.driver.userClassPathFirst=trueво время spark-submit, который изменяет приоритет загрузки зависимостей и, следовательно, поведение spark-job, давая приоритет банкам, которые пользователь добавляет к пути к классам с помощью --jarsопции.

Станислав
источник
2
Вы должны быть осторожны с этим - так как это возможно, чтобы зажечь искру, делая это. Это должно быть последним вариантом решения. Потенциально это может помешать слою, взаимодействующему с пряжей, а также при использовании в режиме клиент-пряжа, хотя я не уверен.
YoYo
Спасибо за внимание. Есть ли способ расставить приоритеты только на 1 банку, которая определенно существует на сервере в старой версии, но вы не можете заменить ее физически и знаете, что не хотите ее использовать?
Станислав
1
Я думаю, в этом случае вы могли бы попробовать именно так, как вы предложили. Не сказал, что это было абсолютно нет. Также помните, что опция помечена как «экспериментальная» - предупреждение, которое следует учитывать! Не существует безопасного способа расстановки приоритетов одной версии библиотеки над другой. В некоторых реализациях это решается перемещением одной из библиотек в другое пространство имен, поэтому вы можете использовать обе версии одновременно.
YoYo
1

Другой вариант конфигурируемого Спарка , относящийся к баночкам и классам, в случае , yarnкак режим развертывания является
Из документации искровой

spark.yarn.jars

Список библиотек, содержащих код Spark для распространения в контейнеры YARN. По умолчанию Spark на YARN будет использовать локальные jar-файлы Spark, но jar-файлы Spark также могут находиться в общедоступном месте на HDFS. Это позволяет YARN кэшировать его на узлах, чтобы его не нужно было распределять при каждом запуске приложения. Например, чтобы указать jar-файлы в HDFS, установите для этой конфигурации значение hdfs: /// some / path. Глобусы разрешены.

spark.yarn.archive

Архив, содержащий необходимые файлы Spark для распространения в кэш YARN. Если установлено, эта конфигурация заменяет spark.yarn.jars, и архив используется во всех контейнерах приложения. Архив должен содержать файлы JAR в своем корневом каталоге. Как и в предыдущем варианте, архив также может быть размещен на HDFS для ускорения распространения файлов.

Пользователи могут настроить этот параметр, чтобы указать свои файлы jar, которые inturn включается в путь к классу драйвера Spark.

Темный мужчина
источник
1

При использовании spark-submit с --master yarn-cluster, jar приложения вместе с любыми jar-файлами, включенными в опцию --jars, будет автоматически перенесен в кластер. URL-адреса, указанные после --jars, должны быть разделены запятыми. Этот список включен в пути к классам драйвера и исполнителя

Пример :

spark-submit - мастер-кластер пряжи --jars ../lib/misc.jar, ../lib/test.jar --class MainClass MainApp.jar

https://spark.apache.org/docs/latest/submitting-applications.html

Шива Гарг
источник
0

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

Если вы укажете --driver-class-pathи выполняете в режиме кластера пряжи, то класс драйвера не обновляется. Мы можем проверить, обновлен ли путь к классу или нет в интерфейсе spark UI или сервере истории обновлений в среде вкладок.

Опция, которая работала для меня, чтобы передать jar, которые содержат расширения каталогов и которые работали в режиме кластера пряжи была --confопцией. Лучше передавать пути классов драйвера и исполнителя as --conf, что добавляет их к самому объекту сеанса Spark, и эти пути отражаются в конфигурации Spark. Но, пожалуйста, убедитесь, что файлы jar размещены в одном кластере.

spark-submit \
  --master yarn \
  --queue spark_queue \
  --deploy-mode cluster    \
  --num-executors 12 \
  --executor-memory 4g \
  --driver-memory 8g \
  --executor-cores 4 \
  --conf spark.ui.enabled=False \
  --conf spark.driver.extraClassPath=/usr/hdp/current/hbase-master/lib/hbase-server.jar:/usr/hdp/current/hbase-master/lib/hbase-common.jar:/usr/hdp/current/hbase-master/lib/hbase-client.jar:/usr/hdp/current/hbase-master/lib/zookeeper.jar:/usr/hdp/current/hbase-master/lib/hbase-protocol.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/scopt_2.11-3.3.0.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/spark-examples_2.10-1.1.0.jar:/etc/hbase/conf \
  --conf spark.hadoop.mapred.output.dir=/tmp \
  --conf spark.executor.extraClassPath=/usr/hdp/current/hbase-master/lib/hbase-server.jar:/usr/hdp/current/hbase-master/lib/hbase-common.jar:/usr/hdp/current/hbase-master/lib/hbase-client.jar:/usr/hdp/current/hbase-master/lib/zookeeper.jar:/usr/hdp/current/hbase-master/lib/hbase-protocol.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/scopt_2.11-3.3.0.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/spark-examples_2.10-1.1.0.jar:/etc/hbase/conf \
  --conf spark.hadoop.mapreduce.output.fileoutputformat.outputdir=/tmp
Tanveer
источник
С Новым Годом!
YoYo
С Новым Годом YoYo
Tanveer
0

В то время как мы отправляем задания spark с помощью утилиты spark-submit, есть опция --jars. Используя эту опцию, мы можем передать файл jar приложениям spark.

бала
источник
О том, что есть этот —jarвариант, было упомянуто оригинальным постером, а также более детально обсуждено более одного ответа. Не похоже, что вы предлагаете что-то новое?
YoYo