图片
- 一. 概念
- 二. 作业调度流程
- 三. Spark运行架构具有以下特点
- 四. spark 详细运行过程
- 1)
- 2)
- 3)
一. 概念
一个Application由一个Driver和若干个Job构成,
一个Job由多个Stage构成,
一个Stage由多个没有Shuffle关系的Task组成(多个RDD算子操作)
stage:宽窄依赖划分
当执行一个Application时,Driver会向集群管理器申请资源,启动Executor,并向Executor发送应用程序代码和文件,然后在Executor上执行Task,运行结束后,执行结果会返回给Driver,或者写到HDFS或者其他数据库中.
二. 作业调度流程
- 构建Spark Application的运行环境(启动SparkContext),SparkContext向资源管理器(可以是Standalone、Mesos或YARN)注册并申请运行Executor资源;
- 资源管理器分配Executor资源并启动StandaloneExecutorBackend,Executor运行情况将随着心跳发送到资源管理器上;
- SparkContext构建成DAG图,将DAG图分解成Stage,并把Taskset发送给Task Scheduler。Executor向SparkContext申请Task
- Task Scheduler将Task发放给Executor运行同时SparkContext将应用程序代码发放给Executor。
- Task在Executor上运行,运行完毕释放所有资源。
三. Spark运行架构具有以下特点
(1)每个Application获取专属的executor进程,该进程在Application期间一直驻留,并以多线程方式运行tasks。这种Application隔离机制有其优势的,无论是从调度角度看(每个Driver调度它自己的任务),还是从运行角度看(来自不同Application的Task运行在不同的JVM中)。当然,这也意味着Spark Application不能跨应用程序共享数据,除非将数据写入到外部存储系统。
(2)Spark与资源管理器无关,只要能够获取executor进程,并能保持相互通信就可以了。
(3)提交SparkContext的Client应该靠近Worker节点(运行Executor的节点),最好是在同一个Rack里,因为Spark Application运行过程中SparkContext和Executor之间有大量的信息交换;如果想在远程集群中运行,最好使用RPC将SparkContext提交给集群,不要远离Worker运行SparkContext。
(4)Task采用了数据本地性和推测执行的优化机制。
四. spark 详细运行过程
1)
- Driver程序的代码运行到action操作,触发了SparkContext的runJob方法。
- SparkContext调用DAGScheduler的runJob函数。
- DAGScheduler把Job划分stage,然后把stage转化为相应的Tasks,把Tasks交给TaskScheduler。
- 通过TaskScheduler把Tasks添加到任务队列当中,交给SchedulerBackend进行资源分配和任务调度, 每个tasks就有多个Threads, 在worker中process(运行)。
- 调度器给Task分配执行Executor,ExecutorBackend负责执行Task。Executor执行结束后,回传给Driver,把执行结果存储到本地或hdfs上
2)
- Driver程序的代码运行到action操作,触发了SparkContext的runJob方法。
- SparkContext调用DAGScheduler的runJob函数。
- DAGScheduler把Job划分stage,然后 DAGScheduler把Job提交stage,DAGScheduler把stage转化为相应的TaskSet,把TaskSet交给TaskScheduler。
- 通过TaskScheduler把Tasks添加到任务队列当中,并把计算任务提交给调度器SchedulableBuilder
- 调度器SchedulableBuilder调度任务TaskScheduler
- TaskScheduler为task分配任务资源,并提交tasks给SchedulerBackend
- 交给SchedulerBackend进行资源分配和任务调度, 将任务提交到Executor上运行, 在Executor(worker)中process(运行)。
- 调度器给Task分配执行Executor,ExecutorBackend负责执行Task。Executor执行结束后,回传给Driver,把执行结果存储到本地或hdfs上
3)
- 我们提交一个任务,任务就叫Application
初始化程序的入口SparkContext,
1.1 初始化DAG Scheduler
1.2 初始化Task Scheduler - Task Scheduler中的ClientEndpoint向master去进行注册并申请资源(CPU Core和Memory)
- Master根据SparkContext的资源申请要求和Worker心跳周期内报告的信息决定在哪个Worker上分配资源,然后在该Worker上获取资源,然后启动StandaloneExecutorBackend;顺便初始化好了一个线程池,通知worker启动Executor
- StandaloneExecutorBackend向Driver(SparkContext)注册,这样Driver就知道哪些Executor为他进行服务了。
到这个时候其实我们的初始化过程基本完成了,我们开始执行transformation的代码,但是代码并不会真正的运行,直到我们遇到一个action操作。生产一个job任务,进行stage的划分 - 发送任务到Executor进行执行
5.1 SparkContext将Applicaiton代码发送给Standalone ExecutorBackend;并且SparkContext解析Applicaiton代码,构建DAG图,并提交给DAG Scheduler分解成Stage(当碰到Action操作时,就会催生Job;每个Job中含有1个或多个Stage,Stage一般在获取外部数据和shuffle之前产生)。
5.2 将Stage(或者称为TaskSet)提交给Task Scheduler。Task Scheduler负责将Task分配到相应的Worker,最后提交给StandaloneExecutorBackend执行;
5.3 对task进行序列化,并根据task的分配算法,分配task
5.4 对接收过来的task进行反序列化,把task封装成一个线程 - 开始执行Task,并向SparkContext报告,反馈任务状态给Driver
- APPlication程序运行完毕后,回收资源