Scala 如果SparkSession未关闭,会发生什么情况?

Scala 如果SparkSession未关闭,会发生什么情况?,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,以下两个之间有什么区别 object Example1 { def main(args: Array[String]): Unit = { try { val spark = SparkSession.builder.getOrCreate // spark code here } finally { spark.close } } } object Exam

以下两个之间有什么区别

object Example1 {
    def main(args: Array[String]): Unit = {
        try {
            val spark = SparkSession.builder.getOrCreate
            // spark code here
        } finally {
            spark.close
        }
    }
}

object Example2 {
    val spark = SparkSession.builder.getOrCreate
    def main(args: Array[String]): Unit = {
        // spark code here
    }
}    
我知道SparkSession实现了Closeable,它暗示需要关闭它。但是,如果SparkSession只是像示例2中那样创建,并且从未直接关闭,我想不出任何问题

如果Spark应用程序成功或失败(并退出主方法),JVM将终止,SparkSession将随之消失。这是正确的吗


IMO:SparkSession是一个单身的事实也不会有太大的区别。

当你完成SparkSession的使用时,你应该总是关闭你的
SparkSession
(即使最终结果只是为了遵循一个良好的实践,即归还你所得到的东西)

关闭
SparkSession
可能会触发释放可提供给其他应用程序的群集资源

SparkSession
是一个会话,因此维护一些消耗JVM内存的资源。您可以拥有任意数量的SparkSessions(请参见重新创建会话),但您不希望它们使用内存,如果您不使用内存,则它们不应该使用内存,因此
关闭
您不再需要的内存

SparkSession
是Spark SQL对Spark Core的包装,因此在封面下(就像在任何Spark应用程序中一样),您将拥有群集资源,即vCore和内存,分配给您的
SparkSession
(通过
SparkContext
)。这意味着,只要您的
SparkContext
正在使用(使用
SparkSession
),集群资源就不会分配给其他任务(不一定是Spark任务,也不一定是提交到集群的其他非Spark应用程序)。这些集群资源是您的,直到您说“我完成了”,这意味着…
close

但是,如果在
close
之后,您只需退出Spark应用程序,就不必考虑执行
close
,因为资源将自动关闭。驱动程序和执行程序的JVM终止,与群集的(心跳)连接也终止,因此最终资源将返回群集管理器,以便它可以提供给其他应用程序使用。

两者都是相同的

Spark会话的
停止
/
关闭
最终调用Spark上下文的
停止

def stop(): Unit = {
  sparkContext.stop()
}

override def close(): Unit = stop()
Spark上下文在退出JVM之前已运行时关闭Spark上下文。请在下面找到创建上下文时添加关机挂钩的spark代码

ShutdownHookManager.addShutdownHook(
  _shutdownHookRef = ShutdownHookManager.SPARK_CONTEXT_SHUTDOWN_PRIORITY) { () =>
  logInfo("Invoking stop() from shutdown hook")
  stop()
}
因此,无论JVM如何退出,都将调用该函数。如果您手动
stop()
,此关闭挂钩将被取消以避免重复

def stop(): Unit = {
  if (LiveListenerBus.withinListenerThread.value) {
    throw new SparkException(
      s"Cannot stop SparkContext within listener thread of ${LiveListenerBus.name}")
  }
  // Use the stopping variable to ensure no contention for the stop scenario.
  // Still track the stopped variable for use elsewhere in the code.
  if (!stopped.compareAndSet(false, true)) {
    logInfo("SparkContext already stopped.")
    return
  }
  if (_shutdownHookRef != null) {
    ShutdownHookManager.removeShutdownHook(_shutdownHookRef)
  }

如果我错了,请纠正我,但是Spark应用程序可能成功或失败。无论哪种情况,Spark应用程序都会终止,与之关联的JVM也会终止。一旦JVM终止,所有资源都被释放(无论我是否调用close)。另外,如果我使用
getOrCreate()
,SparkSession不是一个单例吗?你说“你想玩多少次就玩多少次”是什么意思?谢谢这里有两个问题:1)无论最终结果是失败还是成功,vcores和内存最终将被释放并在集群上可用;2)
SparkSession
可能是单例,因此您可以继承特定于会话的设置,但您也可以使用spark.newSession将其与其他会话隔离。
ShutdownHookManager.addShutdownHook(…)
可以在没有仔细分析的实际观察中找到:如果IntelliJ Scala工作表中未关闭
SparkSession
,则重复的代码执行将失败,并出现无效链接错误。