spark封神之路(3)-spark运行架构

3.1 核心组件

在驱动程序中,通过SparkContext主导应用的执行 SparkContext可以连接不同类型的Cluster Manager(Standalone、YARN、Mesos),连接后,获得集群节点上的Executor 一个Worker节点默认一个Executor,可通过SPARK_WORKER_INSTANCES调整 每个应用获取自己的Executor 每个Task处理一个RDD分区

1、Driver

Spark驱动节点,用于执行Spark任务中的main方法,负责实际代码的执行工作。Driver在Spark作业执行时主要负责:

1)将用户程序转化为job;

2)在Executor之间调度Task;

3)跟踪Executor的执行情况;

4)通过UI查询展示运行情况;

2、Executor

Executor节点是一个JVM进程,负责运行具体任务,任务之间相互独立。

Spark应用启动时,Executor节点被同时启动,并且始终伴随着整个Spark应用的生命周期。

如果有Executor节点发生故障或者崩溃,Spark应用会将出错节点上的任务调度到其他Executor节点上继续运行。

Executor有两个核心功能:

1)负责运行组成Spark应用的任务,并将结果返回给驱动器进程;

2)Executor通过自身的块管理器(Block Manager)为用户程序中要求缓存的RDD提供内存式存储。RDD是直接缓存在Executor进程内的,因此任务可以在运行时充分利用缓存数据加速运算。

3、Spark通用运行流程概述:    

不论Spark以何种模式进行部署,任务提交后,都会先启动Driver进程,随后Driver进程向集群管理器注册应用程序,之后集群管理器根据配置文件分配并启动Executor,当Driver所需的资源全部满足后,Driver开始执行main函数,Spark查询为懒执行,当执行到action算子时开始反向推算,根据宽依赖进行stage划分,随后每一个stage对应一个taskset,taskset中有多个task,根据本地化原则,task会被分发到指定的executor去执行,在任务执行过程中,Executor也会不断与Driver进行通信,报告任务运行情况。

4、YARN Cluster模式: 

在YARN Cluster模式下,任务提交后会和ResourceManager通讯申请启动 ApplicationMaster, 随后 ResourceManager  分配 container,在合适的 NodeManager上启动 ApplicationMaster,此时的 ApplicationMaster 就是 Driver。

Driver 启动后向 ResourceManager 申请 Executor内存,ResourceManager接到ApplicationMaster 的资源申请后会分配 container,然后在合适的 NodeManager 上启动 Executor 进程,Executor 进程启动后会向Driver反向注册,Executor全部注册完成后Driver开始执行main函数,之后执行到 Action 算子时,触发一个 job,并根据宽依赖开始划分 stage,每个stage生成对应的taskSet,之后将 task  分发到各个Executor上执行。

3.2 基本概念

1.ClusterManager:在standalone模式中是Master(主节点),控制整个集群,监控Worker。在YARN模式下是资源管理器。

注意:spark是存储在内存中,不需要管理存储,无论是Master,还是resourcemanager资源管理器,主要都是管理资源的(cpu,内存)。

2.Worker:从节点,负责控制计算节点,启动Executor。在YARN模式中为NodeManager,负责计算节点的控制。

3.Driver:运行Application的main()函数并创建SparkContext(应用程序的入口)。驱动程序,负责向ClusterManager提交作业。和集群的executor进行交互

4.Executor:在worker节点上启动的进程,执行器,在worker node上执行任务的组件、用于启动线程池运行任务。每个Application拥有独立的一组Executors。

5.SparkContext:整个应用的上下文,控制应用的生命周期。

6.RDD:弹性分布式数据集Spark的基本计算单元,一组RDD可形成执行的有向无环图RDD Graph

弹性:既可以在内存,优先在内存存储并计算,如果内存不够,拿磁盘顶上。

数据集:就是一个普通的scala的不可变的集合

分布式:一个完整的RDD数据集,被拆分成多个部分,在不同的机器里面存储。被拆分成的部分称之为该RDD的分区partition,真正存储数据的是partition,RDD不存储数据,RDD就是对这个partition的抽象。又因为RDD是一个scala集合,在scala集合上面有非常多个的算子操作,可以理解为是一个ADT(abstract data type抽象数据类型)

7.DAGScheduler:实现将Spark作业分解成一到多个Stage,每个Stage根据RDD的Partition个数决定Task的个数,然后生成相应的Task set放到TaskScheduler中

8.TaskScheduler:将DAGScheduler划分的stage(task的形式)任务,交付executor去干活

9.Stage:一个Spark作业一般包含一到多个Stage。每次提交的是一个stage阶段的任务。

10.Task:一个job会分成多个stage按照shuffle切分,然后每个stage会有多个Task任务,通过多个Task实现并行运行的功能。

11.Transformations:转换(如:map, filter, groupBy, join等),Transformations操作是Lazy的,一个RDD转换生成另一个RDD的操作不是马上执行,Spark在遇到Transformations操作时只会记录需要这样的操作,并不会去执行,需要等到有Actions操作的时候才会真正启动计算过程进行计算。

12.Actions操作(如:count, collect, save,foreach等),Actions操作会返回结果或把RDD数据写到存储系统中。Actions是触发Spark启动计算的动因

13.SparkEnv:线程级别的上下文,存储运行时的重要组件的引用。SparkEnv内创建并包含如下一些重要组件的引用。

MapOutPutTracker负责Shuffle元信息的存储。

BroadcastManager负责广播变量的控制与元信息的存储。

BlockManager负责存储管理、创建和查找块。

14:MetricsSystem监控运行时性能指标信息

15:SparkConf:负责存储配置信息。

3.2.1 Application

 指的是用户编写的Spark应用程序,包含了Driver功能代码和分布在集群中多个节点上运行的Executor代码。

  Spark应用程序,由一个或多个作业JOB组成,如下图所示。

3.2.2 driver 

 Spark中的Driver即运行上述Application的Main()函数并且创建SparkContext,其中创建SparkContext的目的是为了准备Spark应用程序的运行环境。在Spark中由SparkContext负责和ClusterManager通信,进行资源的申请、任务的分配和监控等;当Executor部分运行完毕后,Driver负责将SparkContext关闭。通常SparkContext代表Driver,如下图所示。

3.2.3 Cluster manager

 指的是在集群上获取资源的外部服务,常用的有:Standalone,Spark原生的资源管理器,由Master负责资源的分配;Haddop Yarn,由Yarn中的ResearchManager负责资源的分配;Messos,由Messos中的Messos Master负责资源管理。

3.2.4 Executor

Application运行在Worker节点上的一个进程,该进程负责运行Task,并且负责将数据存在内存或者磁盘上,每个Application都有各自独立的一批Executor,如下图所示。

3.2.5 Worker计算节点

集群中任何可以运行Application代码的节点,类似于Yarn中的NodeManager节点。在Standalone模式中指的就是通过Slave文件配置的Worker节点,在Spark on Yarn模式中指的就是NodeManager节点,在Spark on Messos模式中指的就是Messos Slave节点,如下图所示。

3.2.6 DAG Scheduler

基于DAG划分Stage 并以TaskSet的形势提交Stage给TaskScheduler;负责将作业拆分成不同阶段的具有依赖关系的多批任务;最重要的任务之一就是:计算作业和任务的依赖关系,制定调度逻辑。在SparkContext初始化的过程中被实例化,一个SparkContext对应创建一个DAGScheduler。

3.2.7 Taskscheduler 任务调度器\

将Taskset提交给worker(集群)运行并回报结果;负责每个具体任务的实际物理调度。如图所示。

3.2.8 JOB

由一个或多个调度阶段所组成的一次计算作业;包含多个Task组成的并行计算,往往由Spark Action催生,一个JOB包含多个RDD及作用于相应RDD上的各种Operation。如图所示。

3.2.9 Stage

一个任务集对应的调度阶段;每个Job会被拆分很多组Task,每组任务被称为Stage,也可称TaskSet,一个作业分为多个阶段;Stage分成两种类型ShuffleMapStage、ResultStage。如图所示。

Application多个job多个Stage:Spark Application中可以因为不同的Action触发众多的job,一个Application中可以有很多的job,每个job是由一个或者多个Stage构成的,后面的Stage依赖于前面的Stage,也就是说只有前面依赖的Stage计算完毕后,后面的Stage才会运行。

划分依据:Stage划分的依据就是宽依赖,何时产生宽依赖,reduceByKey, groupByKey等算子,会导致宽依赖的产生。

核心算法:从后往前回溯,遇到窄依赖加入本stage,遇见宽依赖进行Stage切分。Spark内核会从触发Action操作的那个RDD开始从后往前推,首先会为最后一个RDD创建一个stage,然后继续倒推,如果发现对某个RDD是宽依赖,那么就会将宽依赖的那个RDD创建一个新的stage,那个RDD就是新的stage的最后一个RDD。然后依次类推,继续继续倒推,根据窄依赖或者宽依赖进行stage的划分,直到所有的RDD全部遍历完成为止。

将DAG划分为Stage剖析:如上图,从HDFS中读入数据生成3个不同的RDD,通过一系列transformation操作后再将计算结果保存回HDFS。可以看到这个DAG中只有join操作是一个宽依赖,Spark内核会以此为边界将其前后划分成不同的Stage. 同时我们可以注意到,在图中Stage2中,从map到union都是窄依赖,这两步操作可以形成一个流水线操作,通过map操作生成的partition可以不用等待整个RDD计算结束,而是继续进行union操作,这样大大提高了计算的效率。

将DAG划分为Stage的核心算法

Application多个job多个Stage:Spark Application中可以因为不同的Action触发众多的job,一个Application中可以有很多的job,每个job是由一个或者多个Stage构成的,后面的Stage依赖于前面的Stage,也就是说只有前面依赖的Stage计算完毕后,后面的Stage才会运行。

划分依据:Stage划分的依据就是宽依赖,何时产生宽依赖,reduceByKey, groupByKey等算子,会导致宽依赖的产生。

核心算法:从后往前回溯,遇到窄依赖加入本stage,遇见宽依赖进行Stage切分。Spark内核会从触发Action操作的那个RDD开始从后往前推,首先会为最后一个RDD创建一个stage,然后继续倒推,如果发现对某个RDD是宽依赖,那么就会将宽依赖的那个RDD创建一个新的stage,那个RDD就是新的stage的最后一个RDD。然后依次类推,继续继续倒推,根据窄依赖或者宽依赖进行stage的划分,直到所有的RDD全部遍历完成为止。

3.2.10 TaskSet

由一组关联的,但相互之间没有Shuffle依赖关系的任务所组成的任务集。如图所示。

注意:

1)一个Stage创建一个TaskSet;

2)为Stage的每个Rdd分区创建一个Task,多个Task封装成TaskSet

3.2.11 Task

由一组关联的,但相互之间没有Shuffle依赖关系的任务所组成的任务集。如图所示。

总体的内容如下图:

猜你喜欢

转载自blog.csdn.net/qq_37933018/article/details/117699199