Scala 在编写spark作业时,是否有理由不使用SparkContext.getOrCreate?

Scala 在编写spark作业时,是否有理由不使用SparkContext.getOrCreate?,scala,apache-spark,cassandra,datastax,Scala,Apache Spark,Cassandra,Datastax,我正在写Spark Jobs,在税务局和Cassandra交谈 有时,在Spark作业中执行一系列步骤时,只获取一个新RDD比加入旧RDD更容易 您可以通过调用SparkContext[getOrCreate][1]方法来实现这一点 现在,Spark作业中有时会出现这样的问题:引用SparkContext可能会获取一个不可序列化的大型对象(Spark上下文),并尝试通过网络分发它 在本例中,您正在为该JVM注册一个单例,因此它绕过了序列化问题 有一天,我的技术主管来找我说 不要使用SparkCo

我正在写Spark Jobs,在税务局和Cassandra交谈

有时,在Spark作业中执行一系列步骤时,只获取一个新RDD比加入旧RDD更容易

您可以通过调用
SparkContext[getOrCreate][1]
方法来实现这一点

现在,Spark作业中有时会出现这样的问题:引用SparkContext可能会获取一个不可序列化的大型对象(Spark上下文),并尝试通过网络分发它

在本例中,您正在为该JVM注册一个单例,因此它绕过了序列化问题

有一天,我的技术主管来找我说

不要使用
SparkContext getOrCreate
您可以而且应该使用联接

但他没有给出理由


我的问题是:在编写spark作业时,是否有理由不使用SparkContext.getOrCreate?TL;DR有许多合法的
getOrCreate
方法应用程序,但试图找到执行映射侧连接的漏洞并不是其中之一

一般来说,
SparkContext.getOrCreate
没有什么大问题。该方法有其应用,尽管存在一些警告,但最显著的是:

  • 在其最简单的形式中,它不允许您设置特定于作业的属性,第二个变体(
    (SparkConf)=>SparkContext
    )需要传递
    SparkConf
    ,这与将
    SparkContext
    /
    SparkSession
    保留在范围内几乎没有什么改进
  • 它可能导致不透明的代码具有“魔力”依赖性。它影响测试策略和总体代码可读性
但你的问题是:

现在,Spark作业中有时会出现这样的问题:引用SparkContext可能会获取一个不可序列化的大型对象(Spark上下文),并尝试通过网络分发它

不要使用
SparkContext
getOrCreate
您可以而且应该使用连接

表明您实际使用的方法从未打算使用。通过在executor节点上使用
SparkContext

val rdd: RDD[_] = ???

rdd.map(_ => {
  val sc = SparkContext.getOrCreate()
  ...
})
这绝对是你不应该做的事情

每个Spark应用程序都应该有一个,而且只有一个
SparkContext
在驱动程序上初始化,Apache Spark开发人员多次阻止用户尝试在驱动程序之外使用
SparkContex
。这并不是因为
SparkContext
太大,或者无法序列化,而是因为它是Spark计算模型的基本特征

您可能知道,Spark中的计算由有向无环依赖关系图描述,该图:

  • 以可以转换为实际任务的方式描述处理管道
  • 在任务失败的情况下实现正常恢复
  • 允许适当的资源分配并确保不存在循环依赖关系
让我们关注最后一部分。由于每个executor JVM都有自己的
SparkContext
实例,因此循环依赖关系不是问题-
RDD
数据集
仅存在于其父上下文的范围内,因此您将无法找到属于应用程序驱动程序的对象

适当的资源分配是另一回事。由于每个
SparkContext
都创建自己的Spark应用程序,因此您的“主”进程将无法说明任务中初始化的上下文所使用的资源。同时,集群管理器不会有任何迹象表明应用程序或以某种方式互连。这可能会导致类似死锁的情况

在技术上可以绕过它,谨慎地分配资源和使用管理器级调度池,甚至使用一个单独的集群管理器和它自己的一组或多个资源,但Spark不是为它设计的,它不受支持,总体上会导致脆弱而复杂的设计,其中,正确性取决于配置详细信息、特定群集管理器选择和总体群集利用率