SparkContext作为整个Spark的入口,不管是spark、sparkstreaming、spark sql都需要首先创建一个SparkContext对象,然后基于这个SparkContext进行后续RDD的操作;所以很有必要了解下SparkContext在初始化时干了什么事情。

SparkContext初始化过程主要干了如下几件事情:

1、根据SparkContext的构造入参SparkConf创建SparkEnv;

2、初始化SparkUI;

3、创建TaskScheduler;

4、创建DAGScheduler;

5、启动taskScheduler;

通过源代码说明SparkContext初始化的过程

1、创建SparkEnv

private[spark] val env = SparkEnv.create(
conf, "<driver>", conf.get("spark.driver.host"), conf.get("spark.driver.port").toInt,
isDriver = true, isLocal = isLocal, listenerBus = listenerBus)
SparkEnv.set(env)

2、初始化SparkUI

private[spark] val ui = new SparkUI(this)
ui.bind()

3、创建TaskScheduler:根据spark的运行模式创建不同的SchedulerBackend

private[spark] var taskScheduler = SparkContext.createTaskScheduler(this, master)

private def createTaskScheduler(sc: SparkContext, master: String): TaskScheduler = {
val SPARK_REGEX = """spark://(.*)""".r master match {
case SPARK_REGEX(sparkUrl) =>
val scheduler = new TaskSchedulerImpl(sc)
val masterUrls = sparkUrl.split(",").map("spark://" + _)
val backend = new SparkDeploySchedulerBackend(scheduler, sc, masterUrls)
scheduler.initialize(backend) //为TaskSchedulerImpl中的backend变量初始化
scheduler
}
} TaskSchedulerImpl extends TaskScheduler{
var backend: SchedulerBackend = null
def initialize(backend: SchedulerBackend) {
this.backend = backend //将SparkDeploySchedulerBackend赋值给backend变量
rootPool = new Pool("", schedulingMode, 0, 0)
schedulableBuilder = {
schedulingMode match {
case SchedulingMode.FIFO => //先进先出调度
new FIFOSchedulableBuilder(rootPool)
case SchedulingMode.FAIR => //公平调度
new FairSchedulableBuilder(rootPool, conf)
}
}
schedulableBuilder.buildPools()
}
} private[spark] class SparkDeploySchedulerBackend(scheduler: TaskSchedulerImpl,sc: SparkContext,masters: Array[String])
extends CoarseGrainedSchedulerBackend(scheduler, sc.env.actorSystem) with AppClientListener with Logging { }

4、创建DAGScheduler:根据TaskScheduler创建DAGScheduler,用于接收提交过来的job

//根据TaskScheduler创建DAGScheduler,产生eventProcssActor(是DAGSchedule的通信载体,能接收和发送很多消息)
@volatile private[spark] var dagScheduler: DAGScheduler = new DAGScheduler(this)
class DAGScheduler{ def this(sc: SparkContext) = this(sc, sc.taskScheduler) private def initializeEventProcessActor() {
implicit val timeout = Timeout(30 seconds)
val initEventActorReply = dagSchedulerActorSupervisor ? Props(new DAGSchedulerEventProcessActor(this))
eventProcessActor = Await.result(initEventActorReply, timeout.duration).
asInstanceOf[ActorRef]
} initializeEventProcessActor()
}

//详细分析见DAGScheduler篇章
private[scheduler] class DAGSchedulerEventProcessActor(dagScheduler: DAGScheduler)extends Actor with Logging {{ override def preStart() {
dagScheduler.taskScheduler.setDAGScheduler(dagScheduler)
} def receive = {
case JobSubmitted(jobId, rdd, func, partitions, allowLocal, callSite, listener, properties) =>
dagScheduler.handleJobSubmitted(jobId, rdd, func, partitions, allowLocal, callSite,listener, properties)
......
}
}

5、启动taskScheduler

启动taskScheduler的主要目的是启动相应的SchedulerBackend,并判断是否进行推测式执行任务;

在启动TaskScheduler的过程中会创建Application并向Master发起注册请求;

taskScheduler.start()

TaskSchedulerImpl extends TaskScheduler{
var backend: SchedulerBackend = null
override def start() {
backend.start()
//spark.speculation...
}
} private[spark] class SparkDeploySchedulerBackend(scheduler: TaskSchedulerImpl,sc: SparkContext,masters: Array[String])
extends CoarseGrainedSchedulerBackend(scheduler, sc.env.actorSystem) with AppClientListener with Logging {
var client: AppClient = null
val maxCores = conf.getOption("spark.cores.max").map(_.toInt) override def start() {
super.start() //调用CoarseGrainedSchedulerBackend的start()方法
val driverUrl = "akka.tcp://spark@%s:%s/user/%s".format(
conf.get("spark.driver.host"), conf.get("spark.driver.port"),
CoarseGrainedSchedulerBackend.ACTOR_NAME)
val command = Command(
"org.apache.spark.executor.CoarseGrainedExecutorBackend", args, sc.executorEnvs,
classPathEntries, libraryPathEntries, extraJavaOpts)
val sparkHome = sc.getSparkHome()
val appDesc = new ApplicationDescription(sc.appName, maxCores, sc.executorMemory, command,
sparkHome, sc.ui.appUIAddress, sc.eventLogger.map(_.logDir)) client = new AppClient(sc.env.actorSystem, masters, appDesc, this, conf)
client.start()

}
} class CoarseGrainedSchedulerBackend(scheduler: TaskSchedulerImpl, actorSystem: ActorSystem) extends SchedulerBackend with Logging
var driverActor: ActorRef = null
override def start() {
driverActor = actorSystem.actorOf(
Props(new DriverActor(properties)), name = CoarseGrainedSchedulerBackend.ACTOR_NAME)
}
} class ClientActor extends Actor with Logging{
override def preStart() {
registerWithMaster() //向Master注册Application
}
}

CoarseGrainedSchedulerBackend与CoarseGrainedExecutorBackend通信

private[spark] class CoarseGrainedExecutorBackend(driverUrl: String, executorId: String, hostPort: String, cores: Int)
extends Actor with ExecutorBackend with Logging {
var executor: Executor = null
var driver: ActorSelection = null override def preStart() {
logInfo("Connecting to driver: " + driverUrl)
driver = context.actorSelection(driverUrl)
driver ! RegisterExecutor(executorId, hostPort, cores) //注册Executor,接收方是CoarseGrainedSchedulerBackend
context.system.eventStream.subscribe(self, classOf[RemotingLifecycleEvent])
} override def receive = {
case RegisteredExecutor(sparkProperties)
case LaunchTask(taskDesc)
case KillTask(taskId, _, interruptThread)
case StopExecutor
}
}

Spark分析之SparkContext启动过程分析的更多相关文章

  1. Spark分析之Standalone运行过程分析

    一.集群启动过程--启动Master $SPARK_HOME/sbin/start-master.sh start-master.sh脚本关键内容: spark-daemon.sh start org ...

  2. Zico源代码分析:执行启动过程分析和总结

    事实上已经有童鞋对Zico的源代码和执行过程进行了总结,比如:http://www.cnblogs.com/shuaiwang/p/4522905.html.这里我再补充一些内容. 当我们使用mvn ...

  3. Spark Streaming应用启动过程分析

    本文为SparkStreaming源码剖析的第三篇,主要分析SparkStreaming启动过程. 在调用StreamingContext.start方法后,进入JobScheduler.start方 ...

  4. 《深入理解Spark:核心思想与源码分析》——SparkContext的初始化(叔篇)——TaskScheduler的启动

    <深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...

  5. spark源码阅读--SparkContext启动过程

    ##SparkContext启动过程 基于spark 2.1.0  scala 2.11.8 spark源码的体系结构实在是很庞大,从使用spark-submit脚本提交任务,到向yarn申请容器,启 ...

  6. Disconf源码分析之启动过程分析下(2)

    接上文,下面是第二次扫描的XML配置. <bean id="disconfMgrBean2" class="com.baidu.disconf.client.Dis ...

  7. Linux内核分析(三)内核启动过程分析——构造一个简单的Linux系统

    一.系统的启动(各历史节点) 在最开始的时候,计算机的启动实际上依靠一段二进制码,可以这么理解,他并不是一个真正的计算机启动一道程序.计算机在开始加电的时候几乎是没有任何用处的,因为RAM芯片中包括的 ...

  8. u-boot 源码分析(1) 启动过程分析

    u-boot 源码分析(1) 启动过程分析 文章目录 u-boot 源码分析(1) 启动过程分析 前言 配置 源码结构 api arch board common cmd drivers fs Kbu ...

  9. ASP.Net Core MVC6 RC2 启动过程分析[偏源码分析]

    入口程序 如果做过Web之外开发的人,应该记得这个是标准的Console或者Winform的入口.为什么会这样呢? .NET Web Development and Tools Blog ASP.NE ...

随机推荐

  1. ADB命令行工具使用

    Putty工具连接Android设备 下载链接:https://github.com/sztupy/adbputty/downloads 如上图所示:在HostName中输入transport-usb ...

  2. IntelliJ IDEA 2017.01配置jdk和tomcat

    之前开发Web项目都是用myeclipse或者eclipse,最近想用IDEA这个编辑器去配置一个Web项目,因为是新手,加上对界面的操作不熟练,所以在配置的过程中遇到了一些难题.最后配置成功,并且可 ...

  3. B+与B-树

    1 .B-树定义 B-树是一种平衡的多路查找树,它在文件系统中很有用. 定义:一棵m 阶的B-树,或者为空树,或为满足下列特性的m 叉树:⑴树中每个结点至多有m 棵子树:⑵若根结点不是叶子结点,则至少 ...

  4. java 百分比显示Double类型数值

    DecimalFormat percent = new DecimalFormat("0.00%"); completed_num = (double) involvedTask_ ...

  5. shell 脚本实战笔记(8)--ssh免密码输入执行命令

    前言: ssh命令, 没有指定密码的参数. 以至于在脚本中使用ssh命令的时候, 必须手动输入密码, 才能继续执行. 这样使得脚本的自动化执行变得很差, 尤其当ssh对应的机器数很多的时候, 会令人抓 ...

  6. [LeetCode&Python] Problem 876. Middle of the Linked List

    Given a non-empty, singly linked list with head node head, return a middle node of linked list. If t ...

  7. list.stream().parallel() 并行流

    https://blog.csdn.net/u011001723/article/details/52794455/  :  parallel()其实就是一个并行执行的流.它通过默认的ForkJoin ...

  8. DZY Loves Math系列

    link 好久没写数学题了,再这样下去吃枣药丸啊. 找一套应该还比较有意思的数学题来做. [bzoj3309]DZY Loves Math 简单推一下. \[\sum_{i=1}^n\sum_{j=1 ...

  9. 【LGR-054】洛谷10月月赛II

    [LGR-054]洛谷10月月赛II luogu 成功咕掉Codeforces Round #517的后果就是,我\(\mbox{T4}\)依旧没有写出来.\(\mbox{GG}\) . 浏览器 \( ...

  10. wpf 客户端【JDAgent桌面助手】开发详解(三) 瀑布流效果实现与UI虚拟化优化大数据显示

    目录区域: 业余开发的wpf 客户端终于完工了..晒晒截图 wpf 客户端[JDAgent桌面助手]开发详解-开篇 wpf 客户端[JDAgent桌面助手]详解(一)主窗口 圆形菜单... wpf 客 ...