spark源码解析1-master启动流程
1、在start-master.sh脚本中调用Mater.scala中的main方法
startRpcEnvAndEndpoint()创建RpcEnv
3、在startRpcEnvAndEndpoint中创建RpcEnv(AkkaSystem),创建masterEndPoint(actor),new Master(),实例化Master
4、实例化Master后会调用Master的Onstart()方法
5、 在onStart()中启动webinfo,然后通过定时器循环发送消息给自己
s elf.send(CheckForWorkerTimeOut),通过case object执行
6、在case Object中调用timeOutDeadWorker(),检查超时的work
7、在 timeOutDeadWorker()中检查超时的worker,调用 removeWorker (worker)删除节点,原理就是修改3个集合,其中,会对每个节点尝试15次检查。
8、master启动完成后,在recive()方法中定义大量的case object,等待接受其他actor的请求
spark源码解析2-worker启动流程
在worker启动时,通过脚本start-slave.sh脚本中调用main()在main()中封装参数,调用startRpcEnvAndEndpoint()创建RpcEnv在startRpcEnvAndEndpoint()中创建RpcEnv和endpiont,并实例化Worker,执行Worker的onStart()方法在onStart()方法中主要流程: 创建工作目录启动shuffleservice创建worker webui调用registerWithMaster()向master注册worker在registerWithMaster()方法中" 首先worker回向master注册自己其次会启动定时任务,不断的向自己发送caseclass,调用reregisterWithMaster()在reregisterWithMaster()方法中,如果之前的注册失败,会重复(15、16次)注册自己如果在registerWithMaster()中注册成功,master会向worker发送case object RegisteredWorker,worker接收到消息后,会定时向master发送心跳master接收到心跳信息后,会修改worker的上次心跳时间
spark源码解析3-任务启动流程submit
- 在脚本spark-submit中调用SparkSubmit的main方法
- 在main方法中执行如下:
- 获取提交参数,繁琐就打印
- 通过提交的action匹配是什么行为
- 如果是提交任务,执行submit(args)方法
- 在submit(args)方法中执行如下:
- 准备运行环境
- 定义doRunMain()方法
- 调用runmain()方法,执行用户提交主类的main()方法
- 调用doRunMain()方法
spark源码解析4-任务提交流程
- 在任务启动时,sparksubmit已经通过反射的方式调用了用户提交任务的主类中的main方法,所以,本节以wordcount为例讲解
- 在wordcount中主要由以下几步:
- 创建SparkConf,设置名字
- 创建SparkContent,书写程序
- 程序逻辑,启动任务
- 停止任务
- 所以最重要的源码分析应该在new SparkContent()这个步骤里
- 在281行定义了createSparkEnv()方法,用来创建sparkEnv,但是还没
- 在526行定义了createTaskScheduler()方法,创建了taskscheduler
- 匹配master的模式,SPARK_REGEX(sparkUrl)为standalone模式
- 创建TaskSchedulerImpl
- 定义initialize()方法,接受参数为SchedulerBackend;逻辑中定义调度器类型(默认是FIFO),在创建rootPool等
- 定义start()方法,创建executor的通信actor
- 创建SparkDeploySchedulerBackend()
- 执行TaskSchedulerImpl 的initialize方法,将SparkDeploySchedulerBackend最为参数传入
- 返回SparkDeploySchedulerBackend和TaskSchedulerImpl
- 在529行new DAGScheduler(this),创建了DAGScheduler
- new DAGSchedulerEventProcessLoop()
- 定义inRecive()方法,调用doOnRecive()方法
- 定义doOnRecive()方法中匹配任务方式
- 匹配JobSubmit,调用dagScheduler.handleJobSubmitted()
- 在new DAGScheduler()最后一行,1473行调用eventProcessLoop.start()
- 调用父类EventLoop的start()方法
- 在父类的start()方法中,调用onStart()方法
- 然后调用线程eventThread()的start()方法
- 启动线程的run()方法
- 从队列中获取事件
- 回调DAGSchedulerEventProcessLoop的onRecive()方法处理事件
- 调用TaskSchedulerImpl 的start()方法
- 调用子类SparkDeploySchedulerBackend的start方法,因为在init方法中已经传入了子类
- 在SparkDeploySchedulerBackend的start方法中:
- 调用父类CoarseGrainedSchedulerBackend的start方法
- 注册driverEndPoint
- new DriverEndPoint()
- 执行onstart()
- 定期接收任务,向自己发送ReviveOffers的case object
- 调用makeOffers()方法
- 在makeOffers()方法中,调用launchTask()
- 在launchTask()中,判断集群是否有资源,决定是否发送任务
- 发送任务到CoarseGrainedExecutorBackend
- 在 CoarseGrainedExecutorBackend中提交任务
- 创建AppClient()
- 创建ClientEndPoint,用于和master通信
- 调用AppClient的start()方法,创建AppClient的endpoint
spark源码解析5-executor启动和任务处理流程
- 在创建taskScheduler的时候SparkContext.createTaskScheduler(this, master),进行了 new SparkDeploySchedulerBackend()的步骤,在SparkDeploySchedulerBackend的84行,执行了app运行使用的调度器为CoarseGrainedExecutorBackend
val command = Command("org.apache.spark.executor.CoarseGrainedExecutorBackend", //-----------指定调用的executor是哪个
- 在下面的new AppClient()中,有传入commond
- 查看AppClient的onStart()方法,调用了registerWithMaster(),然后调用了tryRegisterAllMasters()方法
- 在tryRegisterAllMasters()方法中向master发送了消息RegisterApplication(appDescription, self)
- master接收到消息后,向appclient发送消息RegisteredApplication,监听任务运行状态,然后调用schedule()方法
- 在schedule()方法中调用startExecutorOnWorks()方法,在worker上调度和启动executor,在此方法中计算每个worker上可用的资源,并且分配每个worker上需要启动的资源,调用allocateWorkerResourceExecutor方法启动executor
- allocateWorkerResourceExecutor方法中,调用lauchExecutor()方法,启动executor
- 向worker发送消息,启动executor,向appclient发送消息,改变executor的状态