Spark源码分析 – Executor
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的更多相关文章
- Spark源码分析 – 汇总索引
http://jerryshao.me/categories.html#architecture-ref http://blog.csdn.net/pelick/article/details/172 ...
- Spark源码分析(三)-TaskScheduler创建
原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3879151.html 在SparkContext创建过程中会调用createTaskScheduler函 ...
- 【转】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- ...
- Spark源码分析:多种部署方式之间的区别与联系(转)
原文链接:Spark源码分析:多种部署方式之间的区别与联系(1) 从官方的文档我们可以知道,Spark的部署方式有很多种:local.Standalone.Mesos.YARN.....不同部署方式的 ...
- Spark 源码分析 -- task实际执行过程
Spark源码分析 – SparkContext 中的例子, 只分析到sc.runJob 那么最终是怎么执行的? 通过DAGScheduler切分成Stage, 封装成taskset, 提交给Task ...
- Spark源码分析 – BlockManager
参考, Spark源码分析之-Storage模块 对于storage, 为何Spark需要storage模块?为了cache RDD Spark的特点就是可以将RDD cache在memory或dis ...
- Spark源码分析 -- TaskScheduler
Spark在设计上将DAGScheduler和TaskScheduler完全解耦合, 所以在资源管理和task调度上可以有更多的方案 现在支持, LocalSheduler, ClusterSched ...
- Spark源码分析 – SchedulerBackend
SchedulerBackend, 两个任务, 申请资源和task执行和管理 对于SparkDeploySchedulerBackend, 基于actor模式, 主要就是启动和管理两个actor De ...
- Spark源码分析 – Deploy
参考, Spark源码分析之-deploy模块 Client Client在SparkDeploySchedulerBackend被start的时候, 被创建, 代表一个application和s ...
随机推荐
- WWDC 2014 Session笔记 - iOS界面开发的大一统
本文是我的 WWDC 2014 笔记 中的一篇,涉及的 Session 有 What's New in Cocoa Touch Building Adaptive Apps with UIKit Wh ...
- 从零开始,跟我一起做jblog项目(一)引言
从零开始,跟我一起做jblog项目(一)引言 想做一个java版的blog,源自一个很久之前的想法 当时刚学习JAVA的web编程 想买自己的域名,自己的VPS,安装自己的WEB服务 用google ...
- django model 多对多保存
- 安装oracle11g 并且开启APEX 安装
1.Windows下Oracle安装图解----oracle-win-64-11g 详细安装步骤 - souvc - 博客园 oracle 11g 下载网址 一. Oracle 下载 官方下地 ...
- Java callback
Java中的回调(callback)是很重要的一个概念,spring整合hibernate大量使用了这种技术. 究竟怎样才是回调呢? 这是网上最多见到的说明: 1.class A,clas ...
- python学习笔记(6)--有道翻译爬虫
说明: 1. 导入三个模块,urllib.request.urlopen用来打开url链接,urllib.parse的urlencode方法将浏览器network里的data对象转为urlopen的第 ...
- java web hello world(二)基于Servlet理解监听
java web最开始实现是通过Servlet实现,这里就来实现下,最原始的监听是如何实现的. 第一步,创建一个基本的web项目 ,参见(java web hello world(一)) 第二步,we ...
- 转:解决centos netstat和ps感染木马
解决方法:a.去除恶意文件的执行权限chmod 000 /tmp/gates.lod /tmp/moni.lod service sendmail stopchkconfig --level ...
- PCB封装技术
TQFP(thin quad flat package,即薄塑封四角扁平封装)薄四方扁平封装低成本,低高度引线框封装方案. MLF(MicroLeadFrame),MLF接近于芯片级封装(Chip S ...
- Java,Mysql-根据一个给定经纬度的点,进行附近500米地点查询–合理利用算法
Java,Mysql-根据一个给定经纬度的点,进行附近500米地点查询–合理利用算法 LBS 球面距离公式 http://wiki.myoa.info/zh-blog:20 Java,Mysql- ...