Есть ли причина не использовать SparkContext.getOrCreate при написании задания искры?

avatar
hawkeye
3 июля 2018 в 11:36
2326
1
1

Я пишу Spark Jobs, которые разговаривают с Кассандрой в Datastax.

Иногда при выполнении последовательности шагов в задании Spark проще просто получить новый RDD, чем присоединяться к старому.

Это можно сделать, вызвав метод SparkContext [getOrCreate][1].

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

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

Однажды мой технический руководитель подошел ко мне и сказал

Не используйте SparkContext getOrCreate вместо этого вы можете и должны использовать соединения

Но он не назвал причину.

Мой вопрос: Есть ли причина не использовать SparkContext.getOrCreate при написании задания spark?

Источник

Ответы (1)

avatar
zero323
3 июля 2018 в 12:47
4

TL;DR Существует много законных применений методов getOrCreate, но попытка найти лазейку для выполнения соединений на стороне карты не входит в их число.

В целом нет ничего серьезного в SparkContext.getOrCreate. У этого метода есть свои приложения, и хотя есть некоторые оговорки, в первую очередь:

  • В своей простейшей форме он не позволяет вам задавать специфичные для задания свойства, а второй вариант ((SparkConf) => SparkContext) требует передачи SparkConf, что вряд ли является улучшением по сравнению с сохранением SparkContext / SparkSession в область действия.
  • Это может привести к непрозрачному коду с "волшебной" зависимостью. Это влияет на стратегии тестирования и общую читабельность кода.

Однако ваш вопрос, в частности:

Теперь иногда внутри задания Spark возникают опасения, что ссылка на SparkContext может взять большой объект (контекст Spark), который не сериализуем, и попытаться распространить его по сети

и

Не используйте SparkContext getOrCreate вместо этого вы можете и должны использовать соединения

предполагает, что вы на самом деле используете метод не так, как предполагалось. Используя SparkContext на узле исполнителя.

val rdd: RDD[_] = ???

rdd.map(_ => {
  val sc = SparkContext.getOrCreate()
  ...
})

Это определенно то, чего вам не следует делать.

Каждое приложение Spark должно иметь один и только один SparkContext, инициализированный в драйвере, и разработчики Apache Spark во многом предотвратили любые попытки пользователей использовать SparkContex вне драйвера. Дело не в том, что SparkContext велико или невозможно сериализовать, а в том, что это фундаментальная особенность вычислительной модели Spark.

Как вы, наверное, знаете, вычисления в Spark описываются ориентированным ациклическим графом зависимостей, который:

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

Давайте сосредоточимся на последней части. Поскольку каждый исполнитель JVM получает свой собственный экземпляр SparkContext, циклические зависимости не являются проблемой - RDDs и Datasets существуют только в области своего родительского контекста, поэтому вы не сможете использовать объекты, принадлежащие драйверу приложения.

Правильное распределение ресурсов — это совсем другое. Поскольку каждый SparkContext создает собственное приложение Spark, ваш «основной» процесс не сможет учитывать ресурсы, используемые контекстами, инициализированными в задачах. При этом в менеджере кластера не будет никаких указаний на то, что приложение или как-то взаимосвязано. Это, вероятно, вызовет тупиковые ситуации.

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