SparkContext是提交作业到集群的切入点,所以接下来讲解一下SparkContext的初始化过程。
当我们使用spark-submit脚本提交一个作业之后,流程如下:
提交作业之后(省略SparkSubmit的分析不走) -> 反射创建mainClass -> 初始化SparkContext -> 使用sparkContext创建RDD -> 执行count算子runJob(runJob是SparkContext中的)方法触发作业->调用sparkContext中dagScheduler的runJob方法->调用dagScheduler的submitJob方法完成提交,返回一个waiter对象!
通过上面流程可以知道,我们自己的mainClass是通过反射调用的main方法,然后执行mainClass中的我们自己实现的逻辑!SparkContext是一个近2000多行的代码类,负责RDD的创建,广播变量,加速器的调用。可见其重要性接!其概括性主要完成如下任务:
主构造器主要完成的事情:1) 创建SparkEnv 2)创建TaskScheduler 3)创建DAGScheduler 4)启动TaskScheduler
下来正式开始分析SparkContext的初始化过程:
1:SparkContext重要的成员有:
/**
* SparkEnv,Holds all the runtime environment objects for a running Spark instance
*/
private var _env: SparkEnv = _
/**
*_schedulerBackend is a cluster manager ,holded by taskscheduler .
*/
private var _schedulerBackend: SchedulerBackend = _
/**
* taskScheduler,底层的task调度接口
*/
private var _taskScheduler: TaskScheduler = _
/**
* dagScheduler主要负责切分stage的,决定每个Task的最佳位置等功能
*/
@volatile private var _dagScheduler: DAGScheduler = _
2: 在SparkContext主构造器中重要成员的初始化
// Create the Spark execution environment (cache, map output tracker, etc)
//TODO SparkEnv其实就是Driver的RpcEnv环境,_conf是
_env = createSparkEnv(_conf, isLocal, listenerBus)
传入sparkConf变量,isLocal等,SparkEnv其中包含Driver的一个EndPoint,负责缓存,map输出跟踪等。
// Create and start the scheduler
//TODO 传说中的TaskScheduler创建
//TODO 先创建TaskScheduler原因:DAGScheduler的构造参数需要taskScheduler成员(taskScheduler完成的initialize方法调用)
val (sched, ts) = SparkContext.createTaskScheduler(this, master, deployMode)
_schedulerBackend = sched
上面代码完成_schedulerBackend 和_taskScheduler成员的初始化,createTaskScheduler方法是一个重要方法,在createTaskScheduler方法中根据实际的master url创建具体的_schedulerBackend。
例如本地模式的资源管理器LocalSchedulerBackend,standalone模式为 StandaloneSchedulerBackend,yarn模式为YarnSchedulerBackend(spark yarn模块中)。创建完具体SchedulerBackend之后将其设置给taskScheduler,后期taskScheduler提交task时候就是提交给其自身的SchedulerBackend。到此就完成了_schedulerBackend 和_taskScheduler成员的初始化。
//TODO 传说中的DAGScheduler创建
_dagScheduler = new DAGScheduler(this)
接下来开始初始化_dagScheduler,传入当前的sparkContext对象,_dagScheduler持有_taskScheduler引用(因为_dagScheduler划分完毕stage之后,将stage转化为taskSet之后需要提交给_taskScheduler )。
_taskScheduler.start()
启动_taskScheduler,(在SparkStandalone集群中)在taskScheduler的start方法重主要是连接集群,创建StandaloneAppClient,在其Onstart方法中给Master发消息提交提交作业(Master接收到提交作业之后调用master的schedule()的方法进行资源调度)。