Есть ли причина не использовать SparkContext.getOrCreate при написании искрового задания?
Я пишу Spark Jobs, которые говорят с Кассандрой в Datastax.
Иногда при выполнении последовательности шагов в задании Spark легче просто получить новый СДР, чем присоединиться к старому.
Вы можете сделать это, позвонив SparkContext [getOrCreate][1]
метод.
Теперь иногда в задании Spark возникают опасения, что ссылка на SparkContext может взять большой объект (контекст Spark), который нельзя сериализовать, и попытаться распространить его по сети.
В этом случае - вы регистрируете синглтон для этой JVM, и это решает проблему сериализации.
Однажды ко мне пришел мой технический руководитель и сказал
Не использовать
SparkContext getOrCreate
Вы можете и должны использовать соединения вместо
Но он не дал причину.
Мой вопрос: есть ли причина не использовать SparkContext.getOrCreate при написании искрового задания?
1 ответ
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, он не поддерживается и в целом приведет к хрупкой и запутанной конструкции, где корректность зависит от деталей конфигурации, выбора конкретного менеджера кластера и общего использования кластера.