Spark內部如何保證每一個application中只存在一個SparkContext?

Spark有個關因而否容許一個application存在多個SparkContext實例的配置項, 以下:app

spark.driver.allowMultipleContexts: If true, log warnings instead of throwing exceptions when multiple SparkContexts are active. 分佈式

該值默認爲false, 即不容許一個application同時存在一個以上的active SparkContext實例. 如何保證這一點呢?函數

在SparkContext構造函數最開始處獲取是否容許存在多個SparkContext實例的標識allowMultipleContexts, 咱們這裏只討論否的狀況 ( 默認也是否, 即allowMultipleContexts爲false )this

class SparkContext(config: SparkConf) extends Logging with ExecutorAllocationClient {

  //< 若是爲true,有多個SparkContext處於active狀態時記錄warning日誌而不是拋出異常.
  private val allowMultipleContexts: Boolean =
    config.getBoolean("spark.driver.allowMultipleContexts", false)
    
    //< 此處省略n行代碼
}
  //< 注意: 這必須放在SparkContext構造器的最開始
  SparkContext.markPartiallyConstructed(this, allowMultipleContexts)
  
  private[spark] def markPartiallyConstructed(
      sc: SparkContext,
      allowMultipleContexts: Boolean): Unit = {
    SPARK_CONTEXT_CONSTRUCTOR_LOCK.synchronized {
      assertNoOtherContextIsRunning(sc, allowMultipleContexts)
      contextBeingConstructed = Some(sc)
    }
  }
  //< 伴生對象SparkContext包含一組實用的轉換和參數來和各類Spark特性一塊兒使用
object SparkContext extends Logging {
  private val SPARK_CONTEXT_CONSTRUCTOR_LOCK = new Object()
  
  //< 此處省略n行代碼
}

 

結合以上三段代碼, 能夠看出保證一個Spark Application只有一個SparkContext實例的步驟以下:spa

  1. 經過SparkContext伴生對象object SparkContext中維護了一個對象 SPARK_CONTEXT_CONSTRUCTOR_LOCK, 單例SparkContext在一個進程中是惟一的, 因此SPARK_CONTEXT_CONSTRUCTOR_LOCK在一個進程中也是惟一的線程

  2. 函數markPartiallyConstructed中經過synchronized方法保證同一時間只有一個線程能處理日誌

       assertNoOtherContextIsRunning(sc, allowMultipleContexts)
      contextBeingConstructed = Some(sc)

    assertNoOtherContextIsRunning會檢測是否有其餘SparkContext對象正在被構造或已經構造完成, 若allowMultipleContexts爲true且確有正在或者已經完成構造的SparkContext對象, 則拋出異常, 不然完成SparkContext對象構造code

看到這裏, 有人可能會有疑問, 這雖然能保證在一個進程內只有惟一的SparkContext對象, 但Spark是分佈式的, 是否是沒法保證在在其餘節點的進程內會構造SparkContext對象. 其實並不存在這樣的問題, 由於SparkContext只會在Driver中得main函數中聲明並初始化, 也就是說只會在Driver所在節點的一個進程內構造.對象

相關文章
相關標籤/搜索