Spark运行时架构
在分布式环境下,Spark集群采用的时主/从结构。在一个Spark集群中,有一个节点负责中央协调,调度各个分布式工作节点。这个中央协调节点被称为驱动器(Driver),与之对应的工作节点被称为执行器节点(executor).驱动器节点可以和大量的执行器节点进行通信,它们也都作为独立的Java进程运行。驱动器节点和执行器节点一起被称为一个Spark应用(application)
Spark应用通过一个叫做集群管理器(Cluster Manager)的外部服务在集群中的机器上启动。Spark自带的集群管理器被称为独立集群管理器。Spark也能运行在Hadoop YARN和Apache Mesos这两大开源集群机器上。
驱动器节点
Spark驱动器是执行程序中的main()方法的进程。它执行用户编写的用来创建SparkContext、创建RDD,以及进行RDD的转化操作和行动操作的代码。其实,当你启动Spark shell时,你就启动了一个Spark驱动器程序(Spark shell总是会预先加载一个叫做sc的SparkContext对象)。驱动器程序一旦终止,Spark应用也就结束了。
驱动器程序在Spark应用中有两个职责
1.把用户程序转为任务
2.为执行器节点调度任务
把用户程序转为任务
Spark驱动器程序负责把用户程序转为多个物理执行的单元,这些单元也被称为任务(task)。从上层来看,所有的Spark程序都遵循同样的结构:程序从输入数据创建一系列RDD,再使用转化操作派生出新的RDD,最后使用行动操作手机或存储结果RDD中的数据。Spark程序其实是隐式的创建出了一个由操作组成的逻辑上的有向无环图(Directed Acyclic Graph,简称DAG)。当驱动器程序运行时,它会把这个逻辑图转为物理执行计划。
Spark会对逻辑执行计划作一些优化,比如将连续的映射转为流水线化执行,将多个操作合并到一个步骤中等。这样Spark就把逻辑计划转为一系列步骤(stage).而每个步骤又由多个任务组成。这些任务会被打包并送到集群中。任务是Spark中最小的工作单元,用户程序通常要启动成百上千的独立任务。
为执行器节点调度任务
有了物理计划后,Spark驱动器程序必须在各执行器进程间协调人物的调度。执行器进程启动后,会向驱动器进程注册自己,因此,驱动器进程始终对应用中所有的执行器节点有完整的记录。每个执行器节点代表一个能够处理任务和存储RDD数据的进程。
Spark驱动器程序会根据当前的执行器节点集合,尝试把所有任务基于数据所在位置分配给合适的执行器进程。当任务执行时,执行器进程会把缓存数据存储起来,而驱动器进程同样会跟踪这些缓存数据的位置,并且利用这些位置信息来调度以后的任务,以尽量减少数据的网络传输。
驱动器程序会将一些Spark应用的运行时的信息通过网页界面呈现出来,默认在端口4040上。
执行器节点
Spark执行器节点是一种工作进程,负责在Spark作业中运行任务,任务间相互独立。Spark应用启动时,执行器节点就被同时启动,并且始终伴随着整个Spark应用的生命周期而存在。如果有执行器节点发生了异常或崩溃,Spark应用也可以继续执行。执行器有两大作用:
第一,它们负责运行组成Spark应用的任务,并将结果返回给驱动器进程;
第二,他们通过自身的块管理器(Block Manager)为用户程序中要求缓存的RDD提供内存式存储。RDD是直接缓存在执行器进程内的,因此任务可以在运行时充分利用缓存数据加速运算。
集群管理器
Spark依赖于集群管理器来启动执行器节点,而在某些特殊情况下,也依赖集群管理器来启动驱动器节点。集群管理器是Spark中的可插拔式组件。这样,除了Spark自带的独立集群管理器,Spark也可以运行在其他外部集群管理器上,比如YARN和Mesos