Spark执行原理概述

本文详细解析了Apache Spark的核心架构及任务调度流程,包括Master、Worker和Client的职责与交互方式,以及DAGScheduler和TaskScheduler如何高效地调度任务。

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

Spark优点

  • 速度快
    基于内存的计算比MapReduce快100倍以上;
  • 简单易用
    支持多种语言API,快速构建不同应用;
  • 通用
    提供统一的解决方案:SQL、Streaming、MLib、GraphX;
  • 可融合
    资源管理和调度:YARN、Mesos;
    数据存储:HDFS、HBase;

整体架构


整体架构

整体上架构有三部分组成 MasterWorkClient,它们之间通过akka通信,具体的职责如下:
- Master:管理Worker,向Worker提交Application;
- Work:根据Master发送的Application,启动ExecutorBackend;
- Client:向Master注册并监控Application;

消息传递

它们之间的消息传递:
- Master -> Worker:响应Worker注册、Worker重新注册、让Worker启动(停止)Executor和Driver;
- Worker -> Master:注册Worker、汇报Executor和Driver的运行状态、汇报心跳;
- Master -> Driver Client:响应Driver的注册状态、KillDriver的结果、查询Driver当前的运行状态;
- Driver Client -> Master:提交Driver、KillDriver、获取Driver的运行状态;
- Master -> AppClient(ClientActor):回复Application注册结果、告诉AppClient Worker启动了Executor和Executor状态更新了、ApplicationRemoved、Master故障恢复;
- AppClient(ClientActor) -> Master:注册Application、响应Master的故障恢复;
- Executor-> Driver:注册Executor、汇报Executor中运行的Task状态;
- Driver-> Executor:启动(停止)Task、响应Executor的注册请求

任务调度


任务调度逻辑视图

DAGScheduler


DAGScheduler

当最后一个RDD(finalRDD)触发action操作之后,调用 SparkContext#runJob,然后调用 DAGScheduler#handleJobSubmitted完成整个job的提交。

DAGScheduler#submitJob


DAGScheduler#handleJobSubmitted

DAGScheduler将Job从后往前的回溯划分多个 Stage,根据宽依赖中的 ShuffleDependency生成ParentStage,每个Stage由多个逻辑完全相同的、并行执行的Task组成,只是每个Task处理的数据不同。DAGScheduler通过 TaskSet的方式,把其构造的所有Task提交给底层调度器TaskScheduler。
调用链路:

DAGScheduler#handleJobSubmitted 
->  DAGScheduler#submitStage   // 递归地将finalStage依赖的父stage先提交,最后提交finalStage
    -> DAGScheduler#submitMissingTasks  //ShuffleMapStage或者ResultStage创建ShuffleMapTask或ResultTask,即TaskSet 
        -> TaskScheduler#submitTasks

TaskSchedulerImpl


TaskSchedulerImpl

TaskScheduler是一个与具体资源调度解耦合的接口,目前资源调度模式主要有:StandAlone(TaskSchedulerImpl)、Yarn、Mesos、Local、EC2或者其他自定义的资源调度器。
TaskScheduler负责Application的不同Job之间的调度、在Task执行失败重启以及为慢Task启动备份任务。
TaskScheduler#submitTasks是将TaskSet加入到TaskSetManager中进行管理。 SchedulerBuilder#addTaskSetManger确定TaskSetManager的调度顺序,然后按照TaskSetManager的本地特性确定每个Task具体运行在那个ExecutorBackend中。
TaskScheduler通过SparkDeploySchedulerBackend创建AppClient,而AppClient(ClientActor)向Standalone的Master注册Application,然后Master会通过Application的信息为它分配Worker,包括每个worker上使用CPU core的数目等。

CoarseGrainedSchedulerBackend


CoarseGrainedSchedulerBackend

CoarseGrainedSchedulerBackend负责于Cluster Manager交互,负责收集Worker上的计算资源(Executor),并将这些资源传递给TaskSchedulerImpl,由它为Task最终分配资源。Standalone模式下,继承CoarseGrainedSchedulerBackend的SparkDeploySchedulerBackend负责集群资源的获取和调度。
SparkDeploySchedulerBackend#start 启动创建AppClient, AppClient#start启动创建ClientEndPoint(ClientActor),ClientActor向Master注册当前Application;同时SparkDeploySchedulerBackend的父类CoarseGrainedSchedulerBackend启动的时候会创建DriverEndPoint(DriverActor),当CoarseGrainedExecutorBackend启动的时候向DriverActor注册,SparkDeploySchedulerBackend就获取了当前Application拥有的计算资源,TaskSchedulerImpl通过SparkDeploySchedulerBackend获取的计算资源运行Task。
对应到代码当中,CoarseGrainedSchedulerBackend的输入是Executor列表,输出是TaskDescription(Task Id、Executor Id和Task执行环境的依赖信息)二维数组。最后, CoarseGrainedSchedulerBackend.DriverActor#launchTasks将分配到Executor的Task进行分配;
调用链路:

TaskSchedulerImpl#submitTasks  // 
-> CoarseGrainedSchedulerBackend#reviveOffers  // 发送ReviveOffers消息
  -> CoarseGrainedSchedulerBackend.DriverActor#makeOffers // 处理发送来的ReviveOffers消息,WorkOffer表示Executor上可用的资源
     -> TaskSchedulerImpl#resourceOffers  // 为Task运行分配资源
        -> CoarseGrainedSchedulerBackend.DriverActor#launchTasks // 启动Task的运行

CoarseGrainedExecutorBackend


CoarseGrainedExecutorBackend

前面提到,ClientActor向Master注册当前Application,Master根据AppClient提交为Application分配资源选择Worker(Executor)。在选择Worker和确定Executor需要的CPU cores数量之后,Master向Worker发送LaunchExecutor请求,向ClientActor发送Executor已添加的消息,同时更新Master中的Worker信息。
Worker接收到来自Master的LaunchExecutor的消息后,会创建ExecutorRunner。ExecutorRunner会将SparkDeploySchedulerBackend中准备好的ApplicationDescription(CoarseGrainedExecutorBackend)以进程的形式启动起来,CoarseGrainedExecutorBackend启动后,通过传入的driverUrl向在CoarseGrainedSchedulerBackend.DriverActor发送RegisterExecutor,DriverActor接受到RegisterExecutor消息之后,将Executor的信息保存下来,并通过 CoarseGrainedExecutorBackend.DriverActor#launchTasks 实现在Executor上启动Task,同时DriverActor回复RegisteredExecutor,此时CoarseGrainedExecutorBackend收到RegisteredExecutor,会创建一个Executor。

Task


Task

Executor为每个Task生成一个TaskRunner,TaskRunner最终放到ThreadPool中执行,调用Task的run方法来获得任务执行的结果。
ShuffleMapTask#runTask调用RDD的iterator()计算Task,ResultTask计算过程与之类似。区别: ShuffleMapTask#runTask在计算具体的partition后实际上会通过shuffleManager把当前Task的计算结果写入到具体的文件中,操作结束后会把MapStatus发送给DAGScheduler;而 ResultTask#runTask会根据前面Stage的执行结果进行Shuffle,产生整个Job最后的结果。

CoarseGrainedSchedulerBackend#launchTasks 
-> CoarseGrainedExecutorBackend#launchTask 
    -> TaskRunner#run
        -> Task#run
            -> ResultTask#runTask 
                -> RDD#iterator

参考资料:
- Spark技术内幕:Executor分配详解
- Spark系统运行内幕机制循环流程
- 玄畅,图解Spark core.

### Spark on YARN 架构与工作原理概述 Spark on YARN 是 Spark 运行在 Hadoop YARN 框架上的一种模式,YARN 是 Hadoop 的资源管理器,提供统一的资源管理和调度能力。Spark on YARN 的架构设计充分利用了 YARN 的资源管理能力,使得 Spark 能够更高效地运行在 Hadoop 集群上 [^2]。 #### YARN 架构简介 YARN 的架构主要由以下几个组件组成: - **ResourceManager (RM)**:负责集群的资源管理,包括资源的分配和调度。 - **NodeManager (NM)**:负责单个节点的资源管理和任务执行。 - **ApplicationMaster (AM)**:每个应用程序的管理者,负责向 RM 申请资源,并与 NM 协作启动任务。 在 YARN 上运行 Spark 时,Spark 应用程序会被提交到 YARN 集群,由 YARN 负责资源的分配和管理 [^1]。 #### Spark on YARN 的架构 Spark on YARN 的架构与 YARN 的架构紧密集成,主要包括以下几个组件: - **Driver**:负责 Spark 应用程序的主控节点,负责任务的调度和执行。 - **Executor**:在 YARN 容器中运行的 Spark 执行器,负责执行具体的任务。 - **ApplicationMaster**:负责与 YARN 的 ResourceManager 协调资源,并启动 Executor。 在 Spark on YARN 模式下,SparkContext 初始化完成后会与 ApplicationMaster 通信,通过 ApplicationMaster 向 ResourceManager 申请 Container。ApplicationMaster 会通知 NodeManager 在获得的 Container 中启动 Executor [^5]。 #### Spark on YARN 的工作原理 Spark on YARN 的工作原理可以分为以下几个步骤: 1. **提交 Spark 应用程序**:用户通过 `spark-submit` 命令提交 Spark 应用程序到 YARN 集群。 2. **启动 ApplicationMaster**:YARN 会为 Spark 应用程序分配一个 Container 来启动 ApplicationMaster。 3. **申请资源**:ApplicationMaster 向 ResourceManager 申请资源,用于启动 Executor。 4. **启动 Executor**:ResourceManager 分配资源后,ApplicationMaster 会通知 NodeManager 在指定的 Container 中启动 Executor。 5. **执行任务**:Executor 启动后,会与 Driver 通信,获取任务并执行。 6. **结果汇总**:任务执行完成后,结果会汇总到 Driver,最终返回给用户。 在 Yarn-client 模式下,Driver 运行在客户端,通过 ApplicationMaster 向 ResourceManager 获取资源。客户端的 Driver 负责与所有的 Executor Container 进行交互,并将最后的结果汇总。结束掉终端,相当于 kill 掉这个 Spark 应用 [^4]。 #### Spark on YARN 的优势 Spark on YARN 的优势在于其能够充分利用 YARN 的资源管理能力,提供更高的资源利用率和更好的任务调度灵活性。与 Spark 自带的 Standalone 集群相比,YARN 模式能够更好地与其他 Hadoop 生态系统集成,提供更强大的资源管理和调度能力 [^3]。 ```python # 示例代码:提交 Spark 应用程序到 YARN # 使用 spark-submit 命令提交应用程序 # spark-submit --master yarn --deploy-mode client your_spark_application.py ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值