Spark Executor內幕徹底解密(DT大資料夢工廠)

來源:互聯網
上載者:User

標籤:spark executor內幕徹底解密

內容:

1、Spark Executor工作原理圖;

2、ExecutorBackend註冊源碼解密;

3、Executor執行個體化內幕;

4、Executor具體是如何工作的?

1、Master髮指令給Worker啟動Executor;

2、Worker接受到Master發送來的指令,通過ExecutorRunner啟動另外一個進程來運行Executor;

3、此時會啟動粗粒度的ExecutorBackend(CoarseGrainedExecutorBackend);

4、CoarseGrainedExecutorBackend通過發送RegisterExecutor向Driver註冊;

5、Driver在Executor註冊成功之後會返回RegisterExecutor資訊給CoarseGrainedExecutorBackend;

==========Spark Executor工作原理圖 ============

1、需要特別注意的是在CoarseGrainedExecutorBackend啟動時,向Driver註冊Executor其實質是註冊ExecutorBackend執行個體,和Executor執行個體之間沒有直接的關係;

override def onStart() {
  logInfo("Connecting to driver: " + driverUrl)
  rpcEnv.asyncSetupEndpointRefByURI(driverUrl).flatMap { ref =>
    // This is a very fast action so we can use "ThreadUtils.sameThread"
    driver = Some(ref)
    ref.ask[RegisterExecutorResponse](
      RegisterExecutor(executorId, self, hostPort, cores, extractLogUrls))
  }(ThreadUtils.sameThread).onComplete {
    // This is a very fast action so we can use "ThreadUtils.sameThread"
    case Success(msg) => Utils.tryLogNonFatalError {
      Option(self).foreach(_.send(msg)) // msg must be RegisterExecutorResponse
    }
    case Failure(e) => {
      logError(s"Cannot register with driver: $driverUrl", e)
      System.exit(1)
    }
  }(ThreadUtils.sameThread)
}

2、CoarseGrainedExecutorBackend是Executor運行所在的進程名稱,Executor才是真正處理Task對象所在,Executor內部是通過線程池的方式來完成Task的計算的;

3、CoarseGrainedExecutorBackend和Executor是一一對應的;

4、CoarseGrainedExecutorBackend是一個訊息通訊體(其實現了ThreadSafeRPCEndpoint),可以發訊息給Driver並可以接受Driver中發過來的指令,例如啟動Task等;

5、在Driver進程中,有兩個至關重要的EndPoint:

1)ClientEndpoint:主要負責向Master註冊當前的程式,是AppClient的內部成員;

2)DriverEndpoint:這是整個程式運行時候的磁碟機,是CoarseGrainedExecutorBackend的內部成員,這裡會接收到RegisterExecutor 資訊並完成在Driver中的註冊;

6、在Driver中通過ExecutorData封裝並註冊ExecutorBackend資訊到Driver記憶體資料結構executorMapData(CoarseGrainedSchedulerBackend的成員)

7、實際在執行的時候DriverEndpoint會把資訊吸入CoarseGrainedSchedulerBackend的記憶體資料結構executorMapData,所以說最終是確定註冊給了CoarseGrainedSchedulerBackend,也就是說CoarseGrainedSchedulerBackend掌握了為當前程式分配的所有的ExecutorBackend進程,而在每一個ExecutorBackend進行執行個體中會通過Executor對象來負責具體Task的運行。在啟動並執行時候使用synchronized關鍵字來保障executorMapData安全的並發寫操作;

8、CoarseGrainedExecutorBackend收到DriverEndpoint發送過來的RegisteredExecutor訊息後會啟動executor執行個體對象,而executor執行個體對象對象事實上負責真正的Task計算的;

9、建立的ThreadPool中以多線程並發執行和線程複用的方式來高效的執行Spark發過來的Task,接收到Task執行的命令後,會首先把Task封裝在TaskRunner裡面

override def receiveAndReply(context: RpcCallContext): PartialFunction[Any, Unit] = {

  case RegisterExecutor(executorId, executorRef, hostPort, cores, logUrls) =>
    if (executorDataMap.contains(executorId)) {
      context.reply(RegisterExecutorFailed("Duplicate executor ID: " + executorId))
    } else {
      // If the executor‘s rpc env is not listening for incoming connections, `hostPort`
      // will be null, and the client connection should be used to contact the executor.
      val executorAddress = if (executorRef.address != null) {
          executorRef.address
        } else {
          context.senderAddress
        }
      logInfo(s"Registered executor $executorRef ($executorAddress) with ID $executorId")
      addressToExecutorId(executorAddress) = executorId
      totalCoreCount.addAndGet(cores)
      totalRegisteredExecutors.addAndGet(1)
      val data = new ExecutorData(executorRef, executorRef.address, executorAddress.host,
        cores, cores, logUrls)
      // This must be synchronized because variables mutated
      // in this block are read when requesting executors
      CoarseGrainedSchedulerBackend.this.synchronized {
        executorDataMap.put(executorId, data)
        if (numPendingExecutors > 0) {
          numPendingExecutors -= 1
          logDebug(s"Decremented number of pending executors ($numPendingExecutors left)")
        }
      }
      // Note: some tests expect the reply to come after we put the executor in the map
      context.reply(RegisteredExecutor(executorAddress.host))
      listenerBus.post(
        SparkListenerExecutorAdded(System.currentTimeMillis(), executorId, data))
      makeOffers()
    }

private[cluster] class ExecutorData(
   val executorEndpoint: RpcEndpointRef,
   val executorAddress: RpcAddress,
   override val executorHost: String,
   var freeCores: Int,
   override val totalCores: Int,
   override val logUrlMap: Map[String, String]
) extends ExecutorInfo(executorHost, totalCores, logUrlMap)

// Start worker thread pool
private val threadPool = ThreadUtils.newDaemonCachedThreadPool("Executor task launch worker")
private val executorSource = new ExecutorSource(threadPool, executorId)

==========Executor是如何工作的============

1、當Driver發送過來Task的時候,其實是發送給了CoaresGrainedExecutorBackend這個RPCEndpoint,而不是直接發送給了Executor(Executor由於不是訊息迴圈體,所以永遠無法接收遠程發送過來的資訊)

2、ExecutorBackend在收到Driver中發送過來的訊息後會提供調用給launchTask來交給Executor去執行,然後交給線程池中的線程處理;

3、TaskRunner其實JAVA中的Runnable介面的具體實現,在真正工作的時候會交給線程池,線程池中的線程去運行,此時會調用run方法來執行Task;

4、TaskRunner在調用run方法的時候會調用Task的run方法,而Task的run方法會調用runTask,而實際Task有ShuffleMapTask和ResultTask;

case LaunchTask(data) =>
  if (executor == null) {
    logError("Received LaunchTask command but executor was null")
    System.exit(1)
  } else {
    val taskDesc = ser.deserialize[TaskDescription](data.value)
    logInfo("Got assigned task " + taskDesc.taskId)
    executor.launchTask(this, taskId = taskDesc.taskId, attemptNumber = taskDesc.attemptNumber,
      taskDesc.name, taskDesc.serializedTask)
  }

def launchTask(
    context: ExecutorBackend,
    taskId: Long,
    attemptNumber: Int,
    taskName: String,
    serializedTask: ByteBuffer): Unit = {
  val tr = new TaskRunner(context, taskId = taskId, attemptNumber = attemptNumber, taskName,
    serializedTask)
  runningTasks.put(taskId, tr)
  threadPool.execute(tr)
}

650) this.width=650;" src="/e/u261/themes/default/images/spacer.gif" style="background:url("/e/u261/lang/zh-cn/images/localimage.png") no-repeat center;border:1px solid #ddd;" alt="spacer.gif" />

王家林老師名片:

中國Spark第一人

新浪微博:http://weibo.com/ilovepains

公眾號:DT_Spark

部落格:http://blog.sina.com.cn/ilovepains

手機:18610086859

QQ:1740415547

郵箱:[email protected]


本文出自 “一枝花傲寒” 部落格,謝絕轉載!

Spark Executor內幕徹底解密(DT大資料夢工廠)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.