3.1 Spark应用执行机制分析
下面对Spark Application的基本概念和执行机制进行深入介绍。
3.1.1 Spark应用的基本概念
Spark应用(Application)是用户提交的应用程序。Spark运行模式分为:Local、Standalone、YARN、Mesos等。根据Spark Application的Driver Program是否在集群中运行,Spark应用的运行方式又可以分为Cluster模式和Client模式。
下面介绍Spark应用涉及的一些基本概念:
1)SparkContext:Spark应用程序的入口,负责调度各个运算资源,协调各个Worker Node上的Executor。
2)Driver Program:运行Application的main()函数并创建SparkContext。
3)RDD:前面已经讲过,RDD是Spark的核心数据结构,可以通过一系列算子进行操作。当RDD遇到Action算子时,将之前的所有算子形成一个有向无环图(DAG)。再在Spark中转化为Job(Job的概念在后面讲述),提交到集群执行。一个App中可以包含多个Job。
4)Worker Node:集群中任何可以运行Application代码的节点,运行一个或多个Executor进程。
5)Executor:为Application运行在Worker Node上的一个进程,该进程负责运行Task,并且负责将数据存在内存或者磁盘上。每个Application都会申请各自的Executor来处理任务。
下面介绍Spark应用(Application)执行过程中各个组件的概念:
1)Task(任务):RDD中的一个分区对应一个Task, Task是单个分区上最小的处理流程单元
2)TaskSet(任务集):一组关联的,但相互之间没有Shuffle依赖关系的Task集合。
3)Stage(调度阶段):一个TaskSet对应的调度阶段。每个Job会根据RDD的宽依赖关系被切分很多Stage,每个Stage都包含一个TaskSet。
4)Job(作业):由Action算子触发生成的由一个或多个Stage组成的计算作业。
5)Application:用户编写的Spark的应用程序,由一个或多个Job组成。提交到Spark之后,Spark为Application分配资源,将程序转换并执行。
6)DAGScheduler:根据Job构建基于Stage的DAG,并提交Stage给TaskScheduler。
7)TaskScheduler:将Taskset提交给Worker Node集群运行并返回结果。
以上基本概念之间的关系如图3-1所示。
[插图]
图3-1 Spark基本概念之间的关系
3.1.2 Spark应用执行机制概要
Spark Application从提交后到在Worker Node执行,期间经历了一系列变换,具体过程如图3-2所示。
[插图]
图3-2 Spark执行流程
如图3-2所示,前面讲过,当RDD遇见Action算子之后,触发Job提交。提交后的Job在Spark中形成了RDD DAG有向无环图(Directed Acyclic Graph)。RDD DAG经过DAG Scheduler调度之后,根据RDD依赖关系被切分为一系列的Stage。每个Stage包含一组task集合,再经过Task Scheduler之后,task被分配到Worker节点上的Executor线程池执行。如前文所述,RDD中的每一个逻辑分区对应一个物理的数据块,同时每个分区对应一个Task,因此Task也有自己对应的物理数据块,使用用户定义的函数来处理。Spark出于节约内存的考虑,采用了延迟执行的策略,如前文所述,只有Action算子才可以触发整个操作序列的执行。另外,Spark对于中间计算结果也不会重新分配内存,而是在同一个数据块上流水线操作。
Spark使用BlockManager管理数据块,在内存或者磁盘进行存储,如果数据不在本节点,则还可以通过远端节点复制到本机进行计算。在计算时,Spark会在具体执行计算的Worker节点的Executor中创建线程池,Executor将需要执行的任务通过线程池来并发执行。
3.1.3 应用提交与执行
Spark使用Driver进程负责应用的解析、切分Stage并调度Task到Executor执行,包含DAGScheduler等重要对象。Driver进程的运行地点有如下两种:
1)Driver进程运行在Client端,对应用进行管理监控。
2)Master节点指定某个Worker节点启动Driver进程,负责监控整个应用的执行。
针对这两种情况,应用提交及执行过程分别如下:
- Driver运行在Client
用户启动Client端,在Client端启动Driver进程。在Driver中启动或实例化DAGS-cheduler等组件。
1)Driver向Master注册。
2)Worker向Master注册,Master通过指令让Worker启动Executor。
3)Worker通过创建ExecutorRunner线程,进而ExecutorRunner线程启动Executor-Backend进程。
4)ExecutorBackend启动后,向Client端Driver进程内的SchedulerBackend注册,因此Driver进程就可以发现计算资源。
5)Driver的DAGScheduler解析应用中的RDD DAG并生成相应的Stage,每个Stage包含的TaskSet通过TaskScheduler分配给Executor。在Executor内部启动线程池并行化执行Task。
- Driver运行在Worker节点
用户启动客户端,客户端提交应用程序给Master。
1)Master调度应用,指定一个Worker节点启动Driver,即Scheduler-Backend。
2)Worker接收到Master命令后创建DriverRunner线程,在DriverRunner线程内创建SchedulerBackend进程。Driver充当整个作业的主控进程。
3)Master指定其他Worker节点启动Exeuctor,此处流程和上面相似,Worker创建ExecutorRunner线程,启动ExecutorBackend进程。
4)ExecutorBackend启动后,向Driver的SchedulerBackend注册,这样Driver获取了计算资源就可以调度和将任务分发到计算节点执行。
SchedulerBackend进程中包含DAGScheduler,它会根据RDD的DAG切分Stage,生成TaskSet,并调度和分发Task到Executor。对于每个Stage的TaskSet,都会被存放到TaskScheduler中。TaskScheduler将任务分发到Executor,执行多线程并行任务。图3-3为Spark应用的提交与执行示意图。
[插图]
图3-3 Spark应用的提交与执行