Spark有個(gè)關(guān)于是否允許一個(gè)application存在多個(gè)SparkContext實(shí)例的配置項(xiàng), 如下:
**spark.driver.allowMultipleContexts: ** If true, log warnings instead of throwing exceptions when multiple SparkContexts are active.
該值默認(rèn)為false, 即不允許一個(gè)application同時(shí)存在一個(gè)以上的avtive SparkContext實(shí)例. 如何保證這一點(diǎn)呢?
在SparkContext構(gòu)造函數(shù)最開始處獲取是否允許存在多個(gè)SparkContext實(shí)例的標(biāo)識(shí)allowMultipleContexts, 我們這里只討論否的情況 ( 默認(rèn)也是否, 即allowMultipleContexts為false )
class SparkContext(config: SparkConf) extends Logging with ExecutorAllocationClient {
//< 如果為true,有多個(gè)SparkContext處于active狀態(tài)時(shí)記錄warning日志而不是拋出異常.
private val allowMultipleContexts: Boolean =
config.getBoolean("spark.driver.allowMultipleContexts", false)
//< 此處省略n行代碼
}
//< 注意: 這必須放在SparkContext構(gòu)造器的最開始
SparkContext.markPartiallyConstructed(this, allowMultipleContexts)
private[spark] def markPartiallyConstructed(
sc: SparkContext,
allowMultipleContexts: Boolean): Unit = {
SPARK_CONTEXT_CONSTRUCTOR_LOCK.synchronized {
assertNoOtherContextIsRunning(sc, allowMultipleContexts)
contextBeingConstructed = Some(sc)
}
}
//< 伴生對(duì)象SparkContext包含一組實(shí)用的轉(zhuǎn)換和參數(shù)來和各種Spark特性一起使用
object SparkContext extends Logging {
private val SPARK_CONTEXT_CONSTRUCTOR_LOCK = new Object()
//< 此處省略n行代碼
}
結(jié)合以上三段代碼, 可以看出保證一個(gè)Spark Application只有一個(gè)SparkContext實(shí)例的步驟如下:
通過SparkContext伴生對(duì)象object SparkContext中維護(hù)了一個(gè)對(duì)象
SPARK_CONTEXT_CONSTRUCTOR_LOCK
, 單例SparkContext在一個(gè)進(jìn)程中是唯一的, 所以SPARK_CONTEXT_CONSTRUCTOR_LOCK
在一個(gè)進(jìn)程中也是唯一的-
函數(shù)markPartiallyConstructed中通過synchronized方法保證同一時(shí)間只有一個(gè)線程能處理
assertNoOtherContextIsRunning(sc, allowMultipleContexts) contextBeingConstructed = Some(sc)
assertNoOtherContextIsRunning會(huì)檢測(cè)是否有其他SparkContext對(duì)象正在被構(gòu)造或已經(jīng)構(gòu)造完成, 若allowMultipleContexts為true且確有正在或者已經(jīng)完成構(gòu)造的SparkContext對(duì)象, 則拋出異常, 否則完成SparkContext對(duì)象構(gòu)造
看到這里, 有人可能會(huì)有疑問, 這雖然能保證在一個(gè)進(jìn)程內(nèi)只有唯一的SparkContext對(duì)象, 但Spark是分布式的, 是不是無法保證在在其他節(jié)點(diǎn)的進(jìn)程內(nèi)會(huì)構(gòu)造SparkContext對(duì)象. 其實(shí)并不存在這樣的問題, 因?yàn)镾parkContext只會(huì)在Driver中得main函數(shù)中聲明并初始化, 也就是說只會(huì)在Driver所在節(jié)點(diǎn)的一個(gè)進(jìn)程內(nèi)構(gòu)造.