一、构造SparkContext
1.1. 在shell下,通过spark-submit命令将Application提交到集群,此时spark会通过反射的方式,创建和构造一个DriverActor进程出来(scala中的actor类似java的多线程)
1.2. Driver进程会执行我们提交的Application应用程序,一般情况下,先构造SparkConf,再构造SparkContext
1.3. SparkContext在初始化的时候,最主要的做的就是构造DAGScheduler和TaskScheduler。
1.4. TaskScheduler实际上,是会负责,通过它对应的一个后台进程,去连接Spark集群的Master进程注册Application,
1.5. Master接收到Application的注册请求后,会使用自己的资源调度算法(基于调度器standalone,Yarn,Mesos等都有不同的调度算法),在Spark集群的Worker上为这个Application启动Executor
1.6. Master通知worker启动Executor后,Worker会为Application启动Executor进程,
1.7. Executor启动之后,首先做的就是会将自己反向注册到TaskScheduler上去,到此为止SparkContext完成了初始化。
二、运行Application
2.1. 所有Executor都反向注册到Driver上之后,Driver结束SparkContext初始化,会继续执行我们编写的代码
2.2. 每执行一个Action就会创建一个job,job会提交给DAGScheduler
2.3 DAGScheduler会采用自己的stage划分算法将job划分为多个stage,然后每个stage创建一个TaskSet,在此过程中,stage划分算法非常重要,后续会进行详细研究。
2.4 DAGScheduler会将TaskSet传递给TaskScheduler,TaskScheduler会把TaskSet里每一个task提交到Executor上执行(task分配算法)
2.5 Executor每接收一个task都会用TaskRunner来封装task,然后从线程池里面取出一个线程,执行这个task,TaskRunner将我们编写的代码,也就是要执行的算子以及函数,拷贝,反序列化,然后执行Task。
2.6 Task有两种,ShuffleMapTask和ResultTask。只有最后一个stage是ResultTask,之前的stage,都是ShuffleMapTask.
2.7 所以,最后整个Spark应用程序的执行,就是将stage分批次作为taskset提交给executor执行,每个task针对RDD的一个parktition,执行我们定义的算子和函数,以此类推,直到所有操作执行完为止。