1. Application应用
Spark上运行的应用,
包含了驱动器进程(Driver)和集群上的执行器进程(Executor)
每个Application 只有一个Driver 但是可以有多个Executor
2. Application jar
- 包含Spark应用程序的jar文件,
- 有时候开发者会想把应用程序及其依赖打包到一起,形成一个“uber jar”(包含自身以及其所有依赖库的jar包),
- 注意:这时不要把Spark或者hadoop 的库打进来,这些库会在运行时加载。
3. Driver
运行main函数并创建SparkContext的进程
4. Executor执行器
Executor 工作在集群节点上,为某个应用启动的工作进程。
Executor 专门用于运行计算任务,并在磁盘或内存上保存数据,每个应用程序都独享其对应的多个执行器。
Executor 是Spark里的进程模型,可以套用到不同的资源管理器上,与SchedulerBackend配合使用
Executor 内部有一个线程池,有个running task map 和actor接收SchedulerBackend发来的事件
- 事件处理:
launchTasks:根据task描述(taskSet)生成一个TaskRunner 线程丢进running tasks map里, 用线程池执行这个TaskRunner
KillTask:从running tasks map 中取出线程对象,调用它的kill方法
5. Task任务
Task 是下发给执行器的工作单元,
Task 有两种实现 ShuffleMapTask 和 resultTask 与Stage相对应,先前的Stage由shuffleMapTask 组成,job的最后一个Stage由多个ResultTask组成
ShuffleMapTask执行task,并将output分成多个bucket (基于task 的partition)
ResultTask 执行task 并将结果发送给驱动程序。
6. Job作业
Job 是交给调度器的顶层工作项,
Job 是一个并行计算作业,由一组任务(tasks)组成,并由Spark的action 算子触发启动。
有两种类型 Result job 和 Map-stage job
Result job 即计算ResultStage来执行结果的作业 finalStage
Map-stage job 即在一个Stage提交前,计算shuffleMapStage 的output,并可以用作查询计划,并将其提交给下一个阶段前查看map输出的统计内容,可以使用finalStage字段进行两种job类型的区分
Active Job 即正在DAG运行Job
7. Stage阶段
每个作业(job)可以划分为更小的任务集合(taskSet),这就是阶段(Stage),这些阶段彼此依赖,形成一个有向无环图(DG),类似于MapReduce中的map和reduce
在job中计算中间结果的并行运行task集合,这些task在同一个RDD的每个分区上计算同一函数,并拥有同一shuffle依赖,调度器将task的DAG根据shuffle边界进行切割成Stage(必须等到前一个阶段完成后才能提取output)
DAG调度器以拓扑顺序执行Stage,每个Stage都有FirstJobid,标识第一个提交的job,使用FIFO(先入先出)调度策略时,允许早期的job先行计算或者故障恢复
Stage分为两种:ResultStage 和 ShuffleMapStage
ResultStage是在那个action的finalStage,它的task通过在RDD上执行一个函数来直接计算Spark的action
ShuffleMapStage是为shuffle做准备,在map过程中对shuffle需要的数据进行write
如果RDD被多个job重用,相应的Stage可以跨job共享,计算结果是其他Stage的输入
8. SparkContext
- SparkContext 负责程序与Spark集群进行交互,包括申请集群资源、创建RDD、创建累加器(Accumulators)以及广播变量(brodcast)等。
- SparkContext 在Spark应用程序的执行过程中起着主导作用,它与集群管理器,worker节点交互
- 每个JVM 只能激活一个SparkContext对象,创建一个新的SparkContext之前需要停掉之前活跃的SparkContext
- Spark 应用在集群上运行时,包含了多个独立的进程,这些进程与Driver中的SparkContext对象进行协调。
- SparkContext 能够与多种集群管理器通信(包括Spark自带集群管理器、Mesosphere、yarn)。
- SparkContext 连接上集群管理器后,会为该应用在集群各个节点上申请executor,用于执行计算任务和存储数据,接下来Spark将应用程序代码发送给申请到的执行器,最后SparkContext将分割任务(task)发送给各个执行器去执行。
这个结构还有几个值得注意的地方:
每个Spark应用程序都有其对应的多个executor,executor在整个应用的生命周期内都保持运行状态,并以多线程方式运行所有收到的任务,这样可以隔离Spark应用。
从调度角度来看,每个Driver可以独立调度本地应用程序内部的任务。
从执行器角度来看,不同的Spark应用的对应任务将会在不同JVM中运行,然而这种架构也有劣势,多个Spark应用程序之间无法共享数据,除非把数据写到外部存储。
Spark对底层的集群管理器一无所知。只要Spark能申请到executor,并且能够与之通信即可。这种方式可以使Spark相对比较容易在一个支持多种应用的集群管理器上运行(如mesos,yarn)。
Driver程序在整个应用生命周期内必须监听并接收对各个executor的连接请求。因此Driver程序必须能够被所有Worker节点访问到。
因为集群上的任务是由Driver来调度的,所以Driver和Worker节点距离近一些比较好,最好在同一个本地局域网中。如果你需要远程对集群发起请求,最好还是在Driver节点上启动RPC服务,来响应这些远程请求,同时把Driver本身放在距集群Worker节点较近的机器上。
9. SparkConf
- SparkConf 配置Spark参数 Key-Value对,手动设置优先于系统属性
- 设置属性时使用的setXxx方式 使用的是builder模式,返回自身不断的设置
- new SparkConf(false) 使用默认配置