ExecutorBackend

很简单的接口

package org.apache.spark.executor
/**
* A pluggable interface used by the Executor to send updates to the cluster scheduler.
*/
private[spark] trait ExecutorBackend {
def statusUpdate(taskId: Long, state: TaskState, data: ByteBuffer)
}

 

StandaloneExecutorBackend

维护executor, 并负责注册executor以及executor和driver之间的通信

private[spark] class StandaloneExecutorBackend(
driverUrl: String,
executorId: String,
hostPort: String,
cores: Int)
extends Actor
with ExecutorBackend
with Logging {
var executor: Executor = null
var driver: ActorRef = null override def preStart() {
logInfo("Connecting to driver: " + driverUrl)
driver = context.actorFor(driverUrl) // 创建driver actor ref, 以便于和driver通信
driver ! RegisterExecutor(executorId, hostPort, cores) // 向driver注册executor
} override def receive = {
case RegisteredExecutor(sparkProperties) =>
logInfo("Successfully registered with driver")
// Make this host instead of hostPort ?
executor = new Executor(executorId, Utils.parseHostPort(hostPort)._1, sparkProperties) // 当注册成功后, 创建Executor case RegisterExecutorFailed(message) =>
logError("Slave registration failed: " + message)
System.exit(1) case LaunchTask(taskDesc) =>
logInfo("Got assigned task " + taskDesc.taskId)
if (executor == null) {
logError("Received launchTask but executor was null")
System.exit(1)
} else {
executor.launchTask(this, taskDesc.taskId, taskDesc.serializedTask) // 调用executor.launchTask,启动task
} case Terminated(_) | RemoteClientDisconnected(_, _) | RemoteClientShutdown(_, _) =>
logError("Driver terminated or disconnected! Shutting down.")
System.exit(1)
} override def statusUpdate(taskId: Long, state: TaskState, data: ByteBuffer) {
driver ! StatusUpdate(executorId, taskId, state, data) // 当task状态变化时, 报告给driver actor
}
}

Executor

对于Executor, 维护一个threadPool, 可以run多个task, 取决于core的个数

所以对于launchTask, 就是在threadPool中挑个thread去run TaskRunner

private[spark] class Executor(
executorId: String,
slaveHostname: String,
properties: Seq[(String, String)])
extends Logging
{
  // Initialize Spark environment (using system properties read above)
val env = SparkEnv.createFromSystemProperties(executorId, slaveHostname, 0, false, false)
SparkEnv.set(env)

  // Start worker thread pool
val threadPool = new ThreadPoolExecutor(
1, 128, 600, TimeUnit.SECONDS, new SynchronousQueue[Runnable]) def launchTask(context: ExecutorBackend, taskId: Long, serializedTask: ByteBuffer) {
threadPool.execute(new TaskRunner(context, taskId, serializedTask))
}
}

 

TaskRunner

  class TaskRunner(context: ExecutorBackend, taskId: Long, serializedTask: ByteBuffer)
extends Runnable { override def run() {
try {
SparkEnv.set(env)
Accumulators.clear()
val (taskFiles, taskJars, taskBytes) = Task.deserializeWithDependencies(serializedTask) // 反序列化
updateDependencies(taskFiles, taskJars)
val task = ser.deserialize[Task[Any]](taskBytes, Thread.currentThread.getContextClassLoader) // 反序列化
attemptedTask = Some(task)
logInfo("Its epoch is " + task.epoch)
env.mapOutputTracker.updateEpoch(task.epoch)
taskStart = System.currentTimeMillis()
val value = task.run(taskId.toInt) // 调用task.run执行真正的逻辑
val taskFinish = System.currentTimeMillis()
        val accumUpdates = Accumulators.values
val result = new TaskResult(value, accumUpdates, task.metrics.getOrElse(null)) // 生成TaskResult
val serializedResult = ser.serialize(result) // 将TaskResult序列化
logInfo("Serialized size of result for " + taskId + " is " + serializedResult.limit)
        context.statusUpdate(taskId, TaskState.FINISHED, serializedResult) // 将任务完成和taskresult,通过statusUpdate报告给driver
logInfo("Finished task ID " + taskId)
} catch { // 处理各种fail, 同样也要用statusUpdate event通知driver
case ffe: FetchFailedException => {
val reason = ffe.toTaskEndReason
context.statusUpdate(taskId, TaskState.FAILED, ser.serialize(reason))
} case t: Throwable => {
val serviceTime = (System.currentTimeMillis() - taskStart).toInt
val metrics = attemptedTask.flatMap(t => t.metrics)
for (m <- metrics) {
m.executorRunTime = serviceTime
m.jvmGCTime = getTotalGCTime - startGCTime
}
val reason = ExceptionFailure(t.getClass.getName, t.toString, t.getStackTrace, metrics)
context.statusUpdate(taskId, TaskState.FAILED, ser.serialize(reason)) // TODO: Should we exit the whole executor here? On the one hand, the failed task may
// have left some weird state around depending on when the exception was thrown, but on
// the other hand, maybe we could detect that when future tasks fail and exit then.
logError("Exception in task ID " + taskId, t)
//System.exit(1)
}
}
}
}

Spark源码分析 – Executor的更多相关文章

  1. Spark源码分析 – 汇总索引

    http://jerryshao.me/categories.html#architecture-ref http://blog.csdn.net/pelick/article/details/172 ...

  2. Spark源码分析(三)-TaskScheduler创建

    原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3879151.html 在SparkContext创建过程中会调用createTaskScheduler函 ...

  3. 【转】Spark源码分析之-deploy模块

    原文地址:http://jerryshao.me/architecture/2013/04/30/Spark%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8B- ...

  4. Spark源码分析:多种部署方式之间的区别与联系(转)

    原文链接:Spark源码分析:多种部署方式之间的区别与联系(1) 从官方的文档我们可以知道,Spark的部署方式有很多种:local.Standalone.Mesos.YARN.....不同部署方式的 ...

  5. Spark 源码分析 -- task实际执行过程

    Spark源码分析 – SparkContext 中的例子, 只分析到sc.runJob 那么最终是怎么执行的? 通过DAGScheduler切分成Stage, 封装成taskset, 提交给Task ...

  6. Spark源码分析 – BlockManager

    参考, Spark源码分析之-Storage模块 对于storage, 为何Spark需要storage模块?为了cache RDD Spark的特点就是可以将RDD cache在memory或dis ...

  7. Spark源码分析 -- TaskScheduler

    Spark在设计上将DAGScheduler和TaskScheduler完全解耦合, 所以在资源管理和task调度上可以有更多的方案 现在支持, LocalSheduler, ClusterSched ...

  8. Spark源码分析 – SchedulerBackend

    SchedulerBackend, 两个任务, 申请资源和task执行和管理 对于SparkDeploySchedulerBackend, 基于actor模式, 主要就是启动和管理两个actor De ...

  9. Spark源码分析 – Deploy

    参考, Spark源码分析之-deploy模块   Client Client在SparkDeploySchedulerBackend被start的时候, 被创建, 代表一个application和s ...

随机推荐

  1. Qt5中的QtGui

    我在学习Qt查看Qt Creater提供的例子时,遇到了一个小问题.就是明明在代码中包含了QtGui,然而编译的时候还是提示找不到QLabel的定义,以及其他一些类的定义,但是这是官方提供的文档的啊, ...

  2. Unity3D学习(十一):关于UI销毁后图集仍然无法释放问题的解决办法

    前言 最近进行项目性能优化的时候发现的问题. 问题 从大厅进到单局的过程中,会经过选择英雄和加载两个流程,这两个流程对应的UI界面都会有一张几mb左右的贴图作为背景,在进入单局游戏后这两个UI已经销毁 ...

  3. buildroot 修改root密码后无法登录ssh解决方法

    客户说想修改root密码后再登录ssh, 研究了一下,是因为ssh登录是匹配了之前的 密码生成文件,只要把之前的密码生成文件删除就可以. 过程如下: 删除 /etc/ssh/ssh_host*. rm ...

  4. myeclipse 上安装 Maven3<转>

    环境准备: JDK 1.6 Maven 3.0.4 myeclipse 8.6.1 安装 Maven 之前要求先确定你的 JDK 已经安装配置完成.Maven是 Apache 下的一个项目,目前最新版 ...

  5. zend stdio 快捷键

    1.快速跳转到当前所指的函数.变量.方法.类的定义处 F3或者 ctrl+鼠标左键2.ctrl+m 编辑窗口最大化3.ctrl+d 删除当前行4.ctrl+q 定位到最后编辑的地方(全局的)5.ctr ...

  6. easyui datagrid columns 如何取得json 内嵌对象(many-to-one POJO class)

    http://www.iteye.com/problems/44119 http://hi.baidu.com/lapson_85/item/7733586e60b08500a1cf0f8d ———— ...

  7. 多个 label checkbox 组合 显示在同一个水平线上[前提Bootstrap框架]

    <th align="left" valign="middle"> <label class="checkbox inline fo ...

  8. 测试网站访问速度的方法(GTmetrix)

     全方位的免费网站速度测试工具 — GTmetrix 它结合了Google Page Speed和Yahoo! YSlow的网页速度测试功能,并且提供可行的建议帮你改善网站速度.会根据网站的具体情况, ...

  9. TensorFlow基础笔记(7) 图像风格化效果与性能优化进展

    参考 http://hacker.duanshishi.com/?p=1693http://blog.csdn.net/hungryof/article/details/53981959http:// ...

  10. .bss,.data,.text,.rodata

    那天工作时候发现build的时候发现问题, 问题内容是:.text的空间太小了. 我一直以为写代码,就真是弄懂代码怎么写,式样书怎么写,或者弄懂代码的问题所在, 没有想到在build的时候出现问题.结 ...