Spark应用运行架构(Driver、Executor)和提交应用(spark-submit)

本文深入解析Spark的主/从架构,包括驱动器节点、执行器节点及集群管理器的角色与功能,阐述Spark应用的执行流程,并指导如何使用spark-submit部署应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 Spark运行时的架构

在分布式环境下,Spark 集群采用的是主/ 从结构。在一个Spark 集群中,有一个节点负责中央协调,调度各个分布式工作节点。这个中央协调节点被称为驱动器(Driver)节点,与之对应的工作节点被称为执行器(executor)节点。驱动器节点可以和大量的执行器节点进行通信,它们也都作为独立的Java 进程运行。驱动器节点和所有的执行器节点一起被称为一个Spark 应用(application)。
在这里插入图片描述
Spark 应用通过一个叫作集群管理器(Cluster Manager)的外部服务在集群中的机器上启动。Spark 自带的集群管理器被称为独立集群管理器。Spark 也能运行在Hadoop YARN 和Apache Mesos 这两大开源集群管理器上。

1.1 驱动器节点Driver

Spark 驱动器是执行你的程序中的main() 方法的进程。它执行用户编写的用来创建
SparkContext、创建RDD,以及进行RDD 的转化操作和行动操作的代码。其实,当你启动Spark shell 时,你就启动了一个Spark 驱动器程序(Spark shell 总是会预先加载一个叫作sc的SparkContext 对象)。驱动器程序一旦终止,Spark 应用也就结束了。

驱动器程序在Spark 应用中有下述两个职责。

把用户程序转为任务

Spark 驱动器程序负责把用户程序转为多个物理执行的单元,这些单元也被称为任务
(task)。从上层来看,所有的Spark 程序都遵循同样的结构:程序从输入数据创建一系列RDD,再使用转化操作派生出新的RDD,最后使用行动操作收集或存储结果RDD
中的数据。Spark 程序其实是隐式地创建出了一个由操作组成的逻辑上的有向无环图
(Directed Acyclic Graph,简称DAG)。当驱动器程序运行时,它会把这个逻辑图转为物理执行计划。

Spark 会对逻辑执行计划作一些优化,比如将连续的映射转为流水线化执行,将多个操作合并到一个步骤中等。这样Spark 就把逻辑计划转为一系列步骤(stage)。而每个步骤又由多个任务组成。这些任务会被打包并送到集群中。任务是Spark 中最小的工作单元,用户程序通常要启动成百上千的独立任务。

为执行器节点调度任务

有了物理执行计划之后,Spark 驱动器程序必须在各执行器进程间协调任务的调度。执行器进程启动后,会向驱动器进程注册自己。因此,驱动器进程始终对应用中所有的执行器节点有完整的记录。每个执行器节点代表一个能够处理任务和存储RDD 数据的进程。

Spark 驱动器程序会根据当前的执行器节点集合,尝试把所有任务基于数据所在位置分配给合适的执行器进程。当任务执行时,执行器进程会把缓存数据存储起来,而驱动器进程同样会跟踪这些缓存数据的位置,并且利用这些位置信息来调度以后的任务,以尽量减少数据的网络传输。

驱动器程序会将一些Spark 应用的运行时的信息通过网页界面呈现出来,默认在端口
4040 上。比如,在本地模式下,访问http://localhost:4040 就可以看到这个网页了。

1.2 执行器节点Executor

Spark 执行器节点是一种工作进程,负责在Spark 作业中运行任务,任务间相互独立。Spark 应用启动时,执行器节点就被同时启动,并且始终伴随着整个Spark 应用的生命周期而存在。如果有执行器节点发生了异常或崩溃,Spark 应用也可以继续执行。执行器进程有两大作用:第一,它们负责运行组成Spark 应用的任务,并将结果返回给驱动器进程;第二,它们通过自身的块管理器(Block Manager)为用户程序中要求缓存的RDD 提供内存式存储。RDD 是直接缓存在执行器进程内的,因此任务可以在运行时充分利用缓存数据加速运算。

在本地模式下,Spark 驱动器程序和各执行器程序在同一个Java 进程中运行。这是一个特例;执行器程序通常都运行在专用的进程中。

1.3 集群管理器

Spark 依赖于集群管理器来启动执行器节点,而在某些特殊情况下,也依赖集群管理器来启动驱动器节点。集群管理器是Spark 中的可插拔式组件。这样,除了Spark 自带的独立集群管理器,Spark 也可以运行在其他外部集群管理器上,比如YARN 和Mesos。

Spark 文档中始终使用驱动器节点和执行器节点的概念来描述执行Spark应用的进程。而主节点(master)和工作节点(worker)的概念则被用来分别表述集群管理器中的中心化的部分和分布式的部分。这些概念很容易混淆,所以要格外小心。例如,Hadoop YARN 会启动一个叫作资源管理器(Resource Manager)的主节点守护进程,以及一系列叫作节点管理器(Node Manager)的工作节点守护进程。而在YARN 的工作节点上,Spark 不仅可以运行执行器进程,还可以运行驱动器进程。

1.4 启动一个程序

不论你使用的是哪一种集群管理器,你都可以使用Spark 提供的统一脚本spark-submit 将你的应用提交到那种集群管理器上。通过不同的配置选项,spark-submit 可以连接到相应的集群管理器上,并控制应用所使用的资源数量。在使用某些特定集群管理器时,sparksubmit也可以将驱动器节点运行在集群内部(比如一个YARN 的工作节点)。但对于其他的集群管理器,驱动器节点只能被运行在本地机器上。

1.5 Spark应用执行流程概述

(1) 用户通过spark-submit 脚本提交应用。

(2) spark-submit 脚本启动驱动器程序,调用用户定义的main() 方法。

(3) 驱动器程序与集群管理器通信,申请资源以启动执行器节点。

(4) 集群管理器为驱动器程序启动执行器节点。

(5) 驱动器进程执行用户应用中的操作。根据程序中所定义的对RDD 的转化操作和行动操作,驱动器节点把工作以任务的形式发送到执行器进程。

(6) 任务在执行器程序中进行计算并保存结果。

(7) 如果驱动器程序的main() 方法退出,或者调用了SparkContext.stop(),驱动器程序会终止执行器进程,并且通过集群管理器释放资源。

2 使用spark-submit部署应用

Spark 为各种集群管理器提供了统一的工具来提交作业,这个工具是sparksubmit。

bin/spark-submit my_script.py

如果在调用spark-submit 时除了脚本或JAR 包的名字之外没有别的参数,那么这个Spark程序只会在本地执行。当我们希望将应用提交到Spark 独立集群上的时候,可以将独立集群的地址和希望启动的每个执行器进程的大小作为附加标记提供

bin/spark-submit --master spark://host:7077 --executor-memory 10g my_script.py

–master 标记指定要连接的集群URL;在这个示例中,spark:// 表示集群使用独立模式
在这里插入图片描述
除了集群URL,spark-submit 还提供了各种选项,可以让你控制应用每次运行的各项细节。这些选项主要分为两类。第一类是调度信息,比如你希望为作业申请的资源量。第二类是应用的运行时依赖,比如需要部署到所有工作节点上的库和文件。

spark-submit 的一般格式如下:

bin/spark-submit [options] <app jar | python file> [app options]

[options] 是要传给spark-submit 的标记列表。你可以运行spark-submit --help 列出所有可以接收的标记。表7-2 列出了一些常见的标记。

<app jar | python file> 表示包含应用入口的JAR 包或Python 脚本。

[app options] 是传给你的应用的选项。如果你的程序要处理传给main() 方法的参数,它只会得到[app options] 对应的标记,不会得到spark-submit 的标记。
在这里插入图片描述下面展示了一些使用各种选项调用spark-submit 的例子,这些调用语句都比较长。

# 使用独立集群模式提交Java应用
$ ./bin/spark-submit \
--master spark://hostname:7077 \
--deploy-mode cluster \
--class com.databricks.examples.SparkExample \
--name "Example Program" \
--jars dep1.jar,dep2.jar,dep3.jar \
--total-executor-cores 300 \
--executor-memory 10g \
myApp.jar "options" "to your application" "go here"

# 使用YARN客户端模式提交Python应用
$ export HADOOP_CONF_DIR=/opt/hadoop/conf
$ ./bin/spark-submit \
--master yarn \
--py-files somelib-1.2.egg,otherlib-4.4.zip,other-file.py \
--deploy-mode client \
--name "Example Program" \
--queue exampleQueue \
--num-executors 40 \
--executor-memory 10g \
my_script.py "options" "to your application" "go here"

参考 《Spark快速大数据分析》

### 使用 `spark-submit` 运行 Spark 应用程序 #### 提交应用程序至集群 为了在Spark集群上运行应用程序,可以利用位于Spark安装目录下的`spark-submit`脚本[^3]。此工具不仅简化了向不同类型的集群管理器提交作业的过程,还提供了通过一致的方式处理各种环境的需求。 #### 命令结构 基本命令格式如下所示: ```bash ./bin/spark-submit \ --class <main-class> \ --master <master-url> \ --deploy-mode <deploy-mode> \ --conf <key>=<value> \ ... # other options <application-jar> \ [application-arguments] ``` 其中, - `<main-class>` 是指定了包含`main()`函数的应用入口类名; - `<master-url>` 定义了要连接的Master节点URL(例如:local, spark://host:port, mesos://host:port, yarn等); - `<deploy-mode>` 可选参数指定部署模式为client或者cluster,默认是client模式,在这种情况下driver将在本地启动并由客户端进程控制;而在cluster模式下,则会在工作节点之一上创建一个新的JVM来作为Driver Program执行上下文; - `[application-arguments]` 表示传递给应用本身的额外参数列表。 #### 配置选项 除了上述必填项外,还可以设置一系列配置属性以优化性能或调整行为特性。这些可以通过`--conf key=value`的形式添加到命令行中去。比如内存分配、资源请求量以及日志级别等等都可以在此处定义。 #### 实际案例演示 假设有一个名为`example.jar`打包好的Scala/Java项目文件,并希望将其发送到YARN集群上去执行,那么完整的调用方式可能是这样的: ```bash $SPARK_HOME/bin/spark-submit \ --class org.example.MyApp \ --master yarn \ --deploy-mode cluster \ --executor-memory 2G \ --num-executors 50 \ example.jar arg1 arg2 ``` 这里设置了Executor使用的最大堆空间大小(`--executor-memory`)期望获得的工作线程数量(`--num-executors`),同时也指明了两个自定义参数`arg1`, `arg2`. #### 工作流解析 当发出以上指令之后,将会触发一系列内部操作,包括但不限于构建必要的classpath、准备运行时环境变量、初始化ClassLoader实例化所需对象直至最终调用`runMain`方法完成整个过程[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值