Хабр, привет! Вчера на встреча, посвященная Apache Spark , от ребят из Rambler&Co, было довольно много вопросов от участников, связанных с настройкой этого инструмента.
Мы решили пойти по его стопам и поделиться своим опытом.
Тема непростая — поэтому предлагаем вам поделиться своим опытом в комментариях, возможно мы тоже что-то понимаем и используем не так.
Небольшое введение в то, как мы используем Spark. У нас есть трехмесячная программа.
«Специалист по большим данным» , и на протяжении всего второго модуля наши участники работают над этим инструментом.
Соответственно, наша задача как организаторов — подготовить кластер к использованию в таком случае.
Особенность нашего использования в том, что количество людей, одновременно работающих над Spark, может быть равно всей группе.
Например, на семинаре, когда все одновременно что-то пробуют и повторяют за нашим преподавателем.
И это немного – иногда до 40 человек.
Вероятно, в мире не так много компаний, которые сталкиваются с таким вариантом использования.
Далее я расскажу, как и почему мы выбрали те или иные параметры конфига.
Начнем с самого начала.
У Spark есть три варианта запуска в кластере: автономный, с использованием Mesos и с использованием YARN. Мы решили выбрать третий вариант, потому что он имел для нас смысл.
У нас уже есть кластер Hadoop. Наши участники уже хорошо знакомы с его архитектурой.
Давайте использовать ПРЯЖУ.
Дальше интереснее.spark.master=yarn
Каждый из этих трех вариантов развертывания имеет два варианта развертывания: клиент и кластер.
Основанный на документация и различных ссылок в Интернете, можно сделать вывод, что клиент подходит для интерактивной работы — например, через блокнот Jupyter, а кластер больше подходит для производственных решений.
В нашем случае нас интересовала интерактивная работа, поэтому: spark.deploy-mode=client
В общем, отныне Spark как-то будет работать на YARN, но нам этого оказалось мало.
Поскольку у нас программа про большие данные, иногда участникам не хватало того, что было получено в рамках равномерного нарезки ресурсов.
И тут мы обнаружили интересную вещь — динамическое распределение ресурсов.
Вкратце, суть в следующем: если у вас сложная задача и кластер свободен (например, утром), то использование этой опции Spark может дать вам дополнительные ресурсы.
Потребность там рассчитывается по хитрой формуле.
Не будем вдаваться в подробности — работает хорошо.
spark.dynamicAllocation.enabled=true
Мы установили этот параметр, а при запуске Spark вылетел и не запустился.
Правильно, потому что мне пришлось это прочитать документация более внимательно.
Там написано, что для того, чтобы все было ок, нужно еще включить дополнительный параметр.
spark.shuffle.service.enabled=true
Зачем это нужно? Когда наша работа перестанет требовать так много ресурсов, Spark должен вернуть их в общий пул.
Самый трудоемкий этап практически в любой задаче MapReduce — это этап «Перемешать».
Этот параметр позволяет сохранить данные, сгенерированные на этом этапе, и соответственно освободить исполнителей.
А исполнитель — это процесс, который все рассчитывает на работника.
Он имеет определенное количество ядер процессора и определенный объем памяти.
Этот параметр был добавлен.
Казалось, все работает. Стало заметно, что участникам фактически предоставлялось больше ресурсов, когда они в них нуждались.
Но возникла другая проблема — в какой-то момент другие участники проснулись и тоже захотели использовать Spark, но там все было занято, и они были недовольны.
Их можно понять.
Мы начали изучать документацию.
Оказалось, что существует ряд других параметров, с помощью которых можно влиять на процесс.
Например, если исполнитель находится в режиме ожидания, через какое время у него можно будет забрать ресурсы? spark.dynamicAllocation.executorIdleTimeout=120s
В нашем случае, если ваши исполнители две минуты ничего не делают, то просьба вернуть их в общий пул.
Но этого параметра не всегда было достаточно.
Было видно, что человек уже давно ничем не занимается, и ресурсы не высвобождаются.
Оказалось, что есть еще специальный параметр — через какое время выбирать исполнители, содержащие кэшированные данные.
По умолчанию этот параметр был бесконечен! Мы это исправили.
spark.dynamicAllocation.cachedExecutorIdleTimeout=600s
То есть, если ваши исполнители 5 минут ничего не делают, отдайте их в общий пул.
В этом режиме скорость освобождения и выдачи ресурсов для большого количества пользователей стала приличной.
Количество недовольства уменьшилось.
Но мы решили пойти дальше и ограничить максимальное количество исполнителей на одну заявку — по сути на одного участника программы.
spark.dynamicAllocation.maxExecutors=19
Сейчас, конечно, на той стороне есть недовольные — «кластер простаивает, а исполнителей у меня всего 19», но что поделаешь? Нам нужен какой-то правильный баланс.
Вы не можете сделать всех счастливыми.
И еще одна небольшая история, связанная со спецификой нашего случая.
Как-то несколько человек опоздали на практическое занятие, и Спарк почему-то к ним не приступил.
Посмотрели количество свободных ресурсов - вроде есть.
Искра должна запуститься.
К счастью, документация к тому моменту уже была где-то в подкорке добавлена, и мы помнили, что при запуске Spark ищет порт, на котором можно запуститься.
Если первый порт в диапазоне занят, он переходит к следующему по порядку.
Если оно бесплатное, оно захватывает. И есть параметр, который указывает максимальное количество попыток для этого.
По умолчанию — 16. Это число меньше, чем количество человек в нашей группе в классе.
Соответственно, после 16 попыток Спарк сдался и сказал, что я не могу запуститься.
Мы исправили этот параметр.
spark.port.maxRetries=50
Далее я расскажу вам о некоторых настройках, которые не очень связаны со спецификой нашего случая.
Чтобы запустить Spark быстрее, рекомендуется заархивировать папку jars, расположенную в домашнем каталоге SPARK_HOME, и поместить ее в HDFS. Тогда он не будет тратить время на загрузку этих ярников рабочими.
spark.yarn.archive= hdfs:///tmp/spark-archive.zip
Также рекомендуется использовать kryo в качестве сериализатора для более быстрой работы.
Он более оптимизирован, чем стандартный.
spark.serializer=org.apache.spark.serializer.KryoSerializer
А еще есть давняя проблема со Спарком, что он часто вылетает из памяти.
Часто это происходит в тот момент, когда рабочие все рассчитали и отправили результат водителю.
Мы сделали этот параметр для себя больше.
По умолчанию это 1Гб, мы сделали 3. spark.driver.maxResultSize=3072
И наконец, в качестве десерта.
Как обновить Spark до версии 2.1 в дистрибутиве HortonWorks — HDP 2.5.3.0. Данная версия HDP содержит предустановленную версию 2.0, но мы когда-то для себя решили, что Spark развивается довольно активно, и каждая новая версия исправляет некоторые ошибки плюс предоставляет дополнительные возможности, в том числе для Python API, поэтому решили, что нужно сделай обновление.
Скачал с официального сайта версию для Hadoop 2.7. Разархивировал и положил в папку HDP. Мы установили символические ссылки по мере необходимости.
Запускаем - не запускается.
Пишет очень непонятную ошибку.
java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig
Погуглив, мы выяснили, что Spark решил не ждать, пока родится Hadoop, а решил использовать новую версию джерси.
Они сами друг с другом спорят на эту тему в JIRA. Решением было скачать майка версия 1.17.1 .
Поместите это в папку jars в SPARK_HOME, снова заархивируйте и загрузите в HDFS. Эту ошибку мы обошли, но возникла новая, довольно упрощенная.
org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master
При этом пробуем запустить версию 2.0 - все ок.
Попробуйте угадать, что происходит. Мы заглянули в логи этого приложения и увидели примерно следующее: /usr/hdp/${hdp.version}/hadoop/lib/hadoop-lzo-0.6.0.${hdp.version}.
jar
В общем почему-то hdp.version не разрешилась.
Погуглив, мы нашли решение.
Вам нужно зайти в настройки YARN в Ambari и добавить туда параметр для пользовательского сайта Yarn: hdp.version=2.5.3.0-37
Эта магия помогла, и Спарк взлетел.
Мы протестировали несколько наших ноутбуков Jupyter. Все работает. Мы готовы к первому уроку Spark в субботу (завтра)! УПД .
В ходе урока выявилась еще одна проблема.
В какой-то момент YARN перестала предоставлять контейнеры для Spark. В YARN пришлось подправить параметр, который по умолчанию был равен 0,2: yarn.scheduler.capacity.maximum-am-resource-percent=0.8
То есть в распределении ресурсов участвовало только 20% ресурсов.
После изменения параметров мы перезагрузили YARN. Проблема была решена, и остальные участники также смогли запустить искровой контекст. Теги: #spark #apache spark #apache spark #yarn #открытый исходный код #Интеллектуальный анализ данных #Большие данные #Машинное обучение
-
Компьютеры... В Доме? Будущая Семья (1978)
19 Oct, 24 -
Zend Framework И Многоязычие
19 Oct, 24 -
Что Слушал Бог?
19 Oct, 24 -
Вечер Пятницы. Пришло Время Улыбаться!
19 Oct, 24 -
Инвесторы Готовы Рисковать В Израиле
19 Oct, 24