Spark работа в Dataproc динамическое против статического распределения - PullRequest
0 голосов
/ 05 марта 2019

У меня есть кластер Dataproc:

master - 6cores |32 г

рабочий {0-7} - 6 баллов |32g

Максимальное выделение: память: 24576, vCores: 6

Есть два задания для потоковой передачи, одно за другим

Во-первых, я пытался отправитьс настройками по умолчанию spark.dynamicAllocation.enabled=true

В 30% случаев я видел, что первое задание захватило почти всю доступную память, а второе было поставлено в очередь и ждали ресурсы целую вечность.(Это потоковое задание, которое занимало небольшую часть ресурсов в каждом пакете).

Моя вторая попытка состояла в том, чтобы изменить динамическое распределение.Я отправил те же две работы с идентичными конфигурациями:

spark.dynamicAllocation.enabled=false
spark.executor.memory=12g
spark.executor.cores=3
spark.executor.instances=6
spark.driver.memory=8g

Удивительно, но в интерфейсе Yarn я увидел:

7 Запуск контейнеров с 84g Распределение памяти для первой работы.

3 Запущенные контейнеры с выделением памяти 36 г и зарезервированной памятью 72 г для второго задания

В интерфейсе Spark имеется 6 исполнителей и драйвер дляпервое задание и 2 исполнителя и драйвер для второго задания

После повторной попытки (удаления предыдущих заданий и отправки одинаковых заданий) без динамического размещения и одинаковых конфигураций я получил совершенно другой результат:

5 контейнеров 59g Выделение памяти для обоих заданий и 71g Зарезервированная память для второго задания.В spark UI я вижу 4 исполнителя и драйвер в обоих случаях.

У меня есть пара вопросов:

  1. Если dynamicAllocation = false , почему числоКонтейнеры для пряжи отличаются от количества исполнителей?(Сначала я подумал, что дополнительный контейнер для пряжи - это драйвер, но он отличается в памяти.)
  2. Если dynamicAllocation = false , почему Yarn не создает контейнеры по моим точным требованиям - 6 контейнеров(искры исполнителей) для обеих работ.Почему две разные попытки с одной и той же конфигурацией приводят к разным результатам?
  3. Если dynamicAllocation = true - как может быть так, что низко потребляющее искрообразование памяти берет на себя управление всеми ресурсами пряжи

Спасибо

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Планирование Spark и YARN довольно запутанное.Я собираюсь ответить на вопросы в обратном порядке:

3) Вы не должны использовать динамическое распределение в потоковых заданиях Spark.

Проблема заключается в том, что Spark постоянно запрашивает YARN для большего числа исполнителей, посколькуПока есть отставание задач для запуска.Как только задание Spark получает исполнителя, оно сохраняет его до тех пор, пока исполнитель не будет бездействовать в течение 1 минуты (конечно, настраивается).В пакетных заданиях это нормально, потому что, как правило, существует большое непрерывное отставание задач.

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

Чтобы исправить это, старый потоковый API (DStreams) имеет свою собственную версию динамического выделения: https://issues.apache.org/jira/browse/SPARK-12133. Этот JIRAесть дополнительные сведения о том, почему алгоритм Spark для динамического распределения не подходит для потоковой передачи.

Однако Spark Structured Streaming (вероятно, то, что вы используете) не поддерживает динамическое распределение: https://issues.apache.org/jira/browse/SPARK-24815.

tl; dr Spark запрашивает исполнителей на основе своего невыполненного задания, а не на используемой памяти.

1 & 2) @Vamshi T прав.Каждое приложение YARN имеет «Мастер приложений», который отвечает за запрос контейнеров для приложения.Каждое из ваших заданий Spark имеет мастер приложений, который передает запросы на контейнеры от драйвера.

Кажется, ваша конфигурация не соответствует тому, что вы видите в YARN, поэтому не знаете, что там происходит.У вас есть 8 рабочих с 24 г отданы на пряжу.С 12g исполнителями у вас должно быть 2 исполнителя на узел, всего 16 «слотов».Мастер приложений + 6 исполнителей должны иметь по 7 контейнеров на приложение, поэтому оба приложения должны умещаться в 16 слотах.

Мы настраиваем мастер приложений на меньшее количество памяти, поэтому общая память для приложения неочистить кратное 12g.

Если вы хотите, чтобы оба приложения одновременно планировали всех своих исполнителей, вам следует установить spark.executor.instances = 5.

Если вы используете структурированную потоковую передачу, вы можететакже просто запустите оба потоковых задания в одном приложении Spark (отправив их из разных потоков в драйвере).

Полезные ссылки:

0 голосов
/ 06 марта 2019

Я также заметил подобное поведение в своем опыте, и вот что я заметил.Во-первых, распределение ресурсов по пряже зависит от доступных ресурсов в кластере при отправке задания.Когда оба задания отправляются практически в одно и то же время с одинаковой конфигурацией, пряжа распределяет доступные ресурсы поровну между заданиями.Теперь, когда вы добавляете динамическое распределение в микс, все становится немного запутанным / сложным.Теперь в вашем случае:

7 Запуск контейнеров с 84g памяти для первого задания.- Вы получили 7 контейнеров, потому что вы запросили 6 исполнителей, по одному контейнеру для каждого исполнителя, и один дополнительный контейнер предназначен для приложения Master

3 Запуск контейнеров с выделением памяти 36 г и зарезервированной памяти 72 г для второго задания -Поскольку второе задание было отправлено через некоторое время, Yarn распределила оставшиеся ресурсы ... 2 контейнера, по одному для каждого исполнителя и дополнительный для мастера приложения.

Ваши контейнеры никогда не будут соответствовать запрошенным исполнителям ивсегда будет на единицу больше, чем запрашиваемое количество исполнителей, потому что вам нужен один контейнер для запуска мастера приложения.

Надеюсь, что ответит на часть вашего вопроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...