一、SparkContext原理

1、图解

1、当driver启动后会去运行我们的application,在运行application的时候,所有spark程序的第一行都是先创建SparkContext,在创建SparkContext的时候,它的内部创建
两个非常重要的东西DAGSchedule和TaskSchedule,TaskSchedule在创建的时候就会向spark集群的master进行注册。 2、spark最核心的内部会创建3个东西,首先是会createTaskScheduler(),createTaskScheduler()里面会创建三个东西,首先是TaskSchedulerImpl(它其实就是TaskScheduler),
然后创建SparkDeploySchedulerBackend(它在底层会受TaskSchedulerImp的控制,实际上负责与Master的注册,Executor的反注册,Task发送到Executor等操作),然后调用
TaskSchedulerImpl的init()方法,创建SchedulerPool调度池 ,它有不同的优先策略,比如FIFO先进先出。 3、在创建完TaskSchedulerImpl和SparkDeploySchedulerBackend之后,是执行TaskSchedulerImpl的start()方法,这个方法内部实际上会调用SparkDeploySchedulerBackend的
start()方法,在这个start()方法里会创建AppClient,AppClient里会启动一个线程,也就是ClientActor,ClientActor会调用两个方法,registerWithMaster(),会去调用
tryRegisterAllMaster()。这两个方法会向master发送一个东西叫做RegisterApplication(case class,里面封装了application的信息),就会发送到spark集群的Master上面去,
后面回去找worker,然后启动executor,然后executor启动后会反向注册到SparkDeploySchedulerBackend上面去。这就是TaskScheduler的初始化机制。TaskSchedulerImpl底层
主要基于SparkDeploySchedulerBackend工作。 4、DAGScheduler创建的时候有一个非常重要的东西,DAGSchedulerEvenProcessActor,DAGScheduler底层基于该组件进行通讯(线程) 5、SparkUI。4040端口,线上application运行的状态,启动一个jetty服务器,来提供web服务,从而显示网页。

二、SparkContext源码

1、TaskScheduler创建

###SparkContext.scala

// Create and start the scheduler
private[spark] var (schedulerBackend, taskScheduler) =
SparkContext.createTaskScheduler(this, master) //不同的提交模式,会创建不同的TaskScheduler
//standalone模式
case SPARK_REGEX(sparkUrl) =>
//TaskSchedulerImpl()底层通过操作一个SchedulerBackend,针对不同的种类的cluster(standalone、yarn和mesos),调度task。 //他也可以通过使用一个LocalBackend,并且将isLocal参数设置为true,来在本地模式下工作。 //它负责处理一些通用的逻辑,比如决定多个job的调度顺序,启动检查任务执行 //客户端首先应用调度initialize()方法和start()方法,然后通过runTasks()方法提交task sets
val scheduler = new TaskSchedulerImpl(sc)
val masterUrls = sparkUrl.split(",").map("spark://" + _)
val backend = new SparkDeploySchedulerBackend(scheduler, sc, masterUrls)
scheduler.initialize(backend)
(backend, scheduler) ###TaskSchedulerImpl.scala def initialize(backend: SchedulerBackend) {
this.backend = backend
// temporarily set rootPool name to empty
rootPool = new Pool("", schedulingMode, 0, 0)
schedulableBuilder = {
schedulingMode match {
case SchedulingMode.FIFO =>
new FIFOSchedulableBuilder(rootPool)
case SchedulingMode.FAIR =>
new FairSchedulableBuilder(rootPool, conf)
}
}
schedulableBuilder.buildPools()
}

TaskScheduler启动:

###TaskSchedulerImpl.scala

  override def start() {
//重点是调用了SparkDeploySchedulerBackend类的start
backend.start() if (!isLocal && conf.getBoolean("spark.speculation", false)) {
logInfo("Starting speculative execution thread")
import sc.env.actorSystem.dispatcher
sc.env.actorSystem.scheduler.schedule(SPECULATION_INTERVAL milliseconds,
SPECULATION_INTERVAL milliseconds) {
Utils.tryOrExit { checkSpeculatableTasks() }
}
}
} ###SparkDeploySchedulerBackend.scala override def start() {
super.start() // The endpoint for executors to talk to us
val driverUrl = AkkaUtils.address(
AkkaUtils.protocol(actorSystem),
SparkEnv.driverActorSystemName,
conf.get("spark.driver.host"),
conf.get("spark.driver.port"),
CoarseGrainedSchedulerBackend.ACTOR_NAME)
val args = Seq(
"--driver-url", driverUrl,
"--executor-id", "{{EXECUTOR_ID}}",
"--hostname", "{{HOSTNAME}}",
"--cores", "{{CORES}}",
"--app-id", "{{APP_ID}}",
"--worker-url", "{{WORKER_URL}}")
val extraJavaOpts = sc.conf.getOption("spark.executor.extraJavaOptions")
.map(Utils.splitCommandString).getOrElse(Seq.empty)
val classPathEntries = sc.conf.getOption("spark.executor.extraClassPath")
.map(_.split(java.io.File.pathSeparator).toSeq).getOrElse(Nil)
val libraryPathEntries = sc.conf.getOption("spark.executor.extraLibraryPath")
.map(_.split(java.io.File.pathSeparator).toSeq).getOrElse(Nil) // When testing, expose the parent class path to the child. This is processed by
// compute-classpath.{cmd,sh} and makes all needed jars available to child processes
// when the assembly is built with the "*-provided" profiles enabled.
val testingClassPath =
if (sys.props.contains("spark.testing")) {
sys.props("java.class.path").split(java.io.File.pathSeparator).toSeq
} else {
Nil
} // Start executors with a few necessary configs for registering with the scheduler
val sparkJavaOpts = Utils.sparkJavaOpts(conf, SparkConf.isExecutorStartupConf)
val javaOpts = sparkJavaOpts ++ extraJavaOpts
val command = Command("org.apache.spark.executor.CoarseGrainedExecutorBackend",
args, sc.executorEnvs, classPathEntries ++ testingClassPath, libraryPathEntries, javaOpts)
val appUIAddress = sc.ui.map(_.appUIAddress).getOrElse("") //ApplicationDescription非常重要,它代表了当前的这个
//application的一切情况
//包括application最大需要多少CPU core,每个slave上需要多少内存 val appDesc = new ApplicationDescription(sc.appName, maxCores, sc.executorMemory, command,
appUIAddress, sc.eventLogDir, sc.eventLogCodec) //创建APPClient
//APPClient是一个接口,它负责为application与Spark集群进行通信。
//它会接收一个Spark Master的URL,以及一个application,和
//一个集群事件的监听器,以及各种事件发生时监听器的回调函数 client = new AppClient(sc.env.actorSystem, masters, appDesc, this, conf)
client.start() waitForRegistration()
}

2、DAGScheduler创建

###SparkContext.scala

 @volatile private[spark] var dagScheduler: DAGScheduler = _
try {
//DAGScheduler类实现了面向stage的调度机制的高层次的调度层,他会为每个job计算一个stage的DAG(有向无环图),
//追踪RDD和stage的输出是否被物化了(物化就是说,写入了磁盘或者内存等地方),并且寻找一个最少
//消耗(最优、最小)调度机制来运行job,它会将stage作为tasksets提交到底层的TaskSchedulerImple上,
//来在集群上运行它们(task)
//除了处理stage的DAG,它还负责决定运行每个task的最佳位置,基于当前的缓存状态,将这些最佳位置提交底层的
//TaskSchedulerImpl。此外,它会处理理由于shuffle输出文件丢失导致的失败,在这种情况下,旧的stage可能就会
//被重新提交,一个stage内部的失败,如果不是由于shuffle文件丢失所导致的,会被TAskSchedule处理,它会多次重试
//每一个task,直到最后,实在是不行了,才会去取消整个stage
dagScheduler = new DAGScheduler(this)
} catch {
case e: Exception => {
try {
stop()
} finally {
throw new SparkException("Error while constructing DAGScheduler", e)
}
}
}

3、SparkUI的创建

###SparkContext.scala

// Initialize the Spark UI
private[spark] val ui: Option[SparkUI] =
if (conf.getBoolean("spark.ui.enabled", true)) {
Some(SparkUI.createLiveUI(this, conf, listenerBus, jobProgressListener,
env.securityManager,appName))
} else {
// For tests, do not enable the UI
None
} ###SparkUI.scall //默认端口
val DEFAULT_PORT = 4040
def createLiveUI(
sc: SparkContext,
conf: SparkConf,
listenerBus: SparkListenerBus,
jobProgressListener: JobProgressListener,
securityManager: SecurityManager,
appName: String): SparkUI = {
create(Some(sc), conf, listenerBus, securityManager, appName,
jobProgressListener = Some(jobProgressListener))
}

13、SparkContext详解的更多相关文章

  1. 在CentOS上编译安装MySQL 5.7.13步骤详解

    MySQL 5.7主要特性 更好的性能 对于多核CPU.固态硬盘.锁有着更好的优化,每秒100W QPS已不再是MySQL的追求,下个版本能否上200W QPS才是用户更关心的. 更好的InnoDB存 ...

  2. spark[源码]-sparkContext详解[一]

    spark简述 sparkContext在Spark应用程序的执行过程中起着主导作用,它负责与程序和spark集群进行交互,包括申请集群资源.创建RDD.accumulators及广播变量等.spar ...

  3. Java容器解析系列(13) WeakHashMap详解

    关于WeakHashMap其实没有太多可说的,其与HashMap大致相同,区别就在于: 对每个key的引用方式为弱引用; 关于java4种引用方式,参考java Reference 网上很多说 弱引用 ...

  4. Appium自动化(13) - 详解 Keyboard 类里的方法和源码分析

    如果你还想从头学起Appium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1693896.html 前言 Keyboard  类在 a ...

  5. Jmeter 常用函数(13)- 详解 __machineIP

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.html 作用 返回机器(电脑)IP 语法格式 ${_ ...

  6. 【小白学PyTorch】13 EfficientNet详解及PyTorch实现

    参考目录: 目录 1 EfficientNet 1.1 概述 1.2 把扩展问题用数学来描述 1.3 实验内容 1.4 compound scaling method 1.5 EfficientNet ...

  7. Java(13)详解构造方法

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201600.html 博客主页:https://www.cnblogs.com/testero ...

  8. 13.Linux键盘驱动 (详解)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 在上一节分析输入子系统内的intput_handler软件处理部分后,接下来我们开始写input_dev驱动 本节目标: 实现键盘驱动,让开发板的 ...

  9. 【STM32H7教程】第13章 STM32H7启动过程详解

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980 第13章       STM32H7启动过程详解 本章教 ...

随机推荐

  1. 关于Python中的可变对象与不可变对象的区别(转)

    转自:https://blog.csdn.net/rookinzhang/article/details/80259857 Python中可变对象和不可变对象:https://www.cnblogs. ...

  2. zookerper入门、核心概念和使用场景

    zookeeper是一个分布式程序的高性能协调服务,提供集中式信息存储服务,数据存储于内存中,类似文件系统的树形结构,高吞吐量和低延时,集群高可靠,基于zookeeper可以实现分布式统一配置中心.分 ...

  3. Git使用整理

    [本文由水木桶首发于博客园,原文地址:https://www.cnblogs.com/shuimutong/p/11404664.html,未接允许,严禁转载] 背景 很久之前使用的是svn,直接在E ...

  4. 用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

    一,建立一个VC的控制台类型的空工程: 1,从VS菜单中选择“文件”->“新建”->“项目”. 2,在新建项目中选择:“Visual c++”->"Win32"- ...

  5. 关于vue-svg-icon的使用方式

    前言 工作中用到svg格式的图标,既然是svg,当然不想用古老的img方式引用,希望能凭借定义svg的fill属性,随意定义图标的颜色:同时不想将整段svg代码写入组建内,于是找到了使用vue-svg ...

  6. 动态修改app build版本CFBundleVersion

    1.需求说明 2.操作步骤 2.1 新建脚本,选择Build Phases 2.2 点击加号,选择New Run Script Phase 2.3 为了便于识别,双击重命名为 Dynamic Buil ...

  7. Anaconda-Jupyter notebook 如何安装 nbextensions

    系统环境:windows 安装过程中,再次遇到了一地鸡毛,经过不断查询方法,发现前辈大牛们好棒棒! Step1:确定是已经安装好anaconda Step2:要在anaconda prompt模式下运 ...

  8. 【MySQL】SQL语句基础

    一.操作数据库 1.1 创建数据库 1.2 查看数据库 1.3 修改数据库 1.4 删除数据库 1.5 选择数据库 二.操作表 2.1 创建表 2.2 查看表 2.3 修改表 2.4 删除表 三.操作 ...

  9. 阿里云SOP

    阿里云SOP 摘要 注册阿里云账号. 领取及配置ECS. 领取及配置RDS. 部署网站. 注册阿里云账号 在主页点击注册 填入相应的信息 领取及配置ECS 注册后领取免费的ECS,RDS. 打开控制台 ...

  10. Photozoom图像放大的技术一二事

    平行空间下,未知的可能不仅仅是这个世界,还可能是前所未有的未知的探索.那么对于微小型世界来说,我们就需要借助技术的支撑来发现.photozoom就好比是“电子的放大镜”,对我们清晰图像的放大起到了重要 ...