Spark执行流程
- 提交应用程序Application(包括Driver代码和Executor代码)
- 启动Driver,创建SparkContext对象,并加载配置信息、依赖信息和代码(数据加载,算子推演)
- RDD graph:根据用户提交的计算逻辑(Application)中的RDD的转换和动作来生成RDD之间的依赖关系,同时这个计算链也就生成了逻辑上的DAG(有向无环图)。
- DAGScheduler:基于stage的调度器,负责创建Job,将DAG中的RDD划分到不同的Stage,并将Stage作为TaskSet提交给底层调度器TaskScheduler执行。
- TaskScheduler:任务调度器,Spark通过它提交任务并且请求集群调度任务。因其调度的 Task 由 DAGScheduler 创建,所以DAGScheduler是TaskScheduler的前置调度。
- SparkContext可以连接不同类型的Cluster Manager(Standalone,YARN,Mesos)
并根据DAGSchduler向Cluster Manager申请资源(需要多少个Executor) - 一个Worker节点默认一个Executor,如果集群并发度较高(需要运行很多个Application)
则需要开启单节点多Executor模式,通过SPARK_WORKER_INSTANCES调整 - Cluster Manager将Executor的节点信息反馈给SparkContext
- SparkContext通过SchedulerBackend给任务分配Executor资源
再通过TaskScheduler把任务调度到对应的Worker节点上的Executor - Executor有一个线程池,每个线程(core)可以执行一个task
- 当Executor收到一个TaskSet之后,会启动多个线程对这一批task并行计算
- 每一个task处理一个RDD分区,因此每一次并行计算会生成新的RDD分区(即map,flatMap,reduce等转换算子操作)
- 然后Driver会根据新的RDD向Executor提交新的task,直至stage结束(遇到shuffle)
- 因为stage是以shuffle(宽依赖)来划分的,因此这个过程不存在跨分区(窄依赖有利于高并发)。
- 当Executor上的task全部执行完成后,如果需要进行shuffle(发生宽依赖)才能进入下一步计算
则会根据DAG找到相应的Worker节点,将生成的RDD数据集迁移到当前Executor上进行计算 - 以Action算子为Job结束的标志,将结果数据落盘或输出控制台。
通过DAG判断所有Job是否执行完毕,是的话则将结果带回SparkContext,并反馈Cluster Manager,释放SparkContext资源。 - Executor可以为应用程序中要求缓存的RDD提供内存式存储,RDD是直接缓存在Executor进程内的。
如果某个Job过程中产生的RDD数据集要跟其他的Job共用,那么在这个Job计算的过程可以调用cache或persist方法把数据缓存。