原文链接:
https://www.waitingforcode.com/apache-spark-sql/multiple-sparksession-one-sparkcontext/readwww.waitingforcode.com本篇文章第一部分解释了SparkSession和SparkContext两个对象的作用。第二部分讨论了为同一个SparkContext定义多个SparkSession的可能性,最后一部分尝试给出它的一些用例。
SparkSession 和 SparkContext
为了更好地理解本文所讨论的问题,定义我们将要讨论的内容是很重要的。第一个讨论点是SparkContext。它是位于drver端的Spark程序的入口点。它是一个到Spark集群的物化连接,提供了创建rdd、累加器和广播变量所需的所有抽象。我们只能使用一个有效活动的SparkContext,否则spark将抛出一个在同一个JVM中只能有一个运行的SparkContext的错误(参见SPARK-2243)。不过,当我们设置spark.driver.allowMultipleContexts等于true时,这个异常可以避免。
"two SparkContexts created with allowMultipleContexts=true" should "work" in {
val sparkConfiguration = new SparkConf().set("spark.driver.allowMultipleContexts", "true")
val sparkContext1 = new SparkContext("local", "SparkContext#1", sparkConfiguration)
val sparkContext2 = new SparkContext("local", "SparkContext#2", sparkConfiguration)
}
"two SparkContexts" should "fail the processing" in {
val exception = intercept[Exception] {
new SparkContext("local", "SparkContext#1")
new SparkContext("local", "SparkContext#2")
}
exception.getMessage should startWith("Only one SparkContext may be running in this JVM (see SPARK-2243)")
}
然而,在同一个JVM中拥有多个sparkcontext并不是一个好的实现。它对单元测试很有用,顺便说一下,这是它在Apache Spark library的主要用途。在测试范围之外,不能保证我们的程序在多个活动的SparkContext中正确地工作。此外,这也使得对我们的程序数据流管理更加困难。工作流并不是孤立的——一个上下文的潜在故障可能影响另一个上下文,甚至可能破坏整个JVM。它还会给driver程序做的所有事情带来额外的硬件压力。即使我们用toLocalIterator收集了一部分数据,但是要处理的数据总是比单独的进程多很多倍。
SparkContext的一个缺点是只能处理某一特定的场景。比如为了使用Hive,我们需要使用HiveContext,想处理结构化数据,就必须使用SQLContext实例,想处理实时流数据,就得用StreamingContext。然而SparSession解决了这个问题,它是所有不同管道的一个公共入口点。SparkSession的实例是用一个通用的构建器构造的,除了Hive需要调用enableHive()方法。
SparkSessions 共享 SparkContext
如前所述,同一个JVM拥有多个sparkcontext在技术上是可行的,但同时也被认为是一种不好的实现。Spark提供了一个工厂方法getOrCreate()来防止创建多个SparkContext:
"two SparkContext created with a factory method" should "not fail" in {