简单Spark源码分析

1 Master启动流程

1、在start-master.sh脚本中调用Mater.scala中的main方法
2、在main方法中封装spark参数,并调用startRpcEnvAndEndpoint()创建RpcEnv
3、在startRpcEnvAndEndpoint中创建RpcEnv(AkkaSystem),创建masterEndPoint(actor),new Master(),实例化Master
4、实例化Master后会调用Master的Onstart()方法
5、在onStart()中启动webinfo,然后通过定时器循环发送消息给自己
self.send(CheckForWorkerTimeOut),通过case object执行
6、在case Object中调用timeOutDeadWorker(),检查超时的work
7、在timeOutDeadWorker()中检查超时的worker,调用removeWorker(worker)删除节点,原理就是修改3个集合,其中,会对每个节点尝试15次检查。
8、master启动完成后,在recive()方法中定义大量的case object,等待接受其他actor的请求

简单Spark源码分析_第1张图片

2 worker启动流程

  1. 在worker启动时,通过脚本start-slave.sh脚本中调用main()
  2. 在main()中封装参数,调用startRpcEnvAndEndpoint()创建RpcEnv
  3. 在startRpcEnvAndEndpoint()中创建RpcEnv和endpiont,并实例化Worker,执行Worker的onStart()方法
  4. 在onStart()方法中主要流程:
    a. 创建工作目录
    b. 启动shuffleservice
    c. 创建worker webui
    d. 调用registerWithMaster()向master注册worker
  5. 在registerWithMaster()方法中”
    a. 首先worker回向master注册自己
    b. 其次会启动定时任务,不断的向自己发送caseclass,调用reregisterWithMaster()
  6. 在reregisterWithMaster()方法中,如果之前的注册失败,会重复(15、16次)注册自己
  7. 如果在registerWithMaster()中注册成功,master会向worker发送case object RegisteredWorker,worker接收到消息后,会定时向master发送心跳
  8. master接收到心跳信息后,会修改worker的上次心跳时间

简单Spark源码分析_第2张图片

3 任务启动流程submit

  1. 在脚本spark-submit中调用SparkSubmit的main方法
  2. 在main方法中执行如下:
    a. 获取提交参数,繁琐就打印
    b. 通过提交的action匹配是什么行为
    c. 如果是提交任务,执行submit(args)方法
  3. 在submit(args)方法中执行如下:
    a. 准备运行环境
    b. 定义doRunMain()方法
    i. 调用runmain()方法,执行用户提交主类的main()方法
    c. 调用doRunMain()方法

简单Spark源码分析_第3张图片

4 任务提交流程

  1. 在任务启动时,sparksubmit已经通过反射的方式调用了用户提交任务的主类中的main方法,所以,本节以wordcount为例讲解
  2. 在wordcount中主要由以下几步:
    a. 创建SparkConf,设置名字
    b. 创建SparkContent,书写程序
    c. 程序逻辑,启动任务
    d. 停止任务
  3. 所以最重要的源码分析应该在new SparkContent()这个步骤里
    a. 在281行定义了createSparkEnv()方法,用来创建sparkEnv,但是还没
    b. 在526行定义了createTaskScheduler()方法,创建了taskscheduler
    i. 匹配master的模式,SPARK_REGEX(sparkUrl)为standalone模式
    ii. 创建TaskSchedulerImpl
  4. 定义initialize()方法,接受参数为SchedulerBackend;逻辑中定义调度器类型(默认是FIFO),在创建rootPool等
  5. 定义start()方法,创建executor的通信actor
    iii. 创建SparkDeploySchedulerBackend()
    iv. 执行TaskSchedulerImpl 的initialize方法,将SparkDeploySchedulerBackend最为参数传入
    v. 返回SparkDeploySchedulerBackend和TaskSchedulerImpl
    c. 在529行new DAGScheduler(this),创建了DAGScheduler
    i. new DAGSchedulerEventProcessLoop()
  6. 定义inRecive()方法,调用doOnRecive()方法
  7. 定义doOnRecive()方法中匹配任务方式
    a. 匹配JobSubmit,调用dagScheduler.handleJobSubmitted()
    ii. 在new DAGScheduler()最后一行,1473行调用eventProcessLoop.start()
  8. 调用父类EventLoop的start()方法
    a. 在父类的start()方法中,调用onStart()方法
    b. 然后调用线程eventThread()的start()方法
    c. 启动线程的run()方法
    i. 从队列中获取事件
    ii. 回调DAGSchedulerEventProcessLoop的onRecive()方法处理事件
    d. 调用TaskSchedulerImpl 的start()方法
    i. 调用子类SparkDeploySchedulerBackend的start方法,因为在init方法中已经传入了子类
    ii. 在SparkDeploySchedulerBackend的start方法中:
  9. 调用父类CoarseGrainedSchedulerBackend的start方法
    a. 注册driverEndPoint
    b. new DriverEndPoint()
    i. 执行onstart()
  10. 定期接收任务,向自己发送ReviveOffers的case object
  11. 调用makeOffers()方法
  12. 在makeOffers()方法中,调用launchTask()
  13. 在launchTask()中,判断集群是否有资源,决定是否发送任务
  14. 发送任务到CoarseGrainedExecutorBackend
  15. 在 CoarseGrainedExecutorBackend中提交任务
  16. 创建AppClient()
    a. 创建ClientEndPoint,用于和master通信
  17. 调用AppClient的start()方法,创建AppClient的endpoint

简单Spark源码分析_第4张图片

5 Executor启动和任务处理流程

  1. 在创建taskScheduler的时候SparkContext.createTaskScheduler(this, master),进行了 new SparkDeploySchedulerBackend()的步骤,在SparkDeploySchedulerBackend的84行,执行了app运行使用的调度器为CoarseGrainedExecutorBackend
val command = Command("org.apache.spark.executor.CoarseGrainedExecutorBackend", //-----------指定调用的executor是哪个
  1. 在下面的new AppClient()中,有传入commond
  2. 查看AppClient的onStart()方法,调用了registerWithMaster(),然后调用了tryRegisterAllMasters()方法
  3. 在tryRegisterAllMasters()方法中向master发送了消息RegisterApplication(appDescription, self)
  4. master接收到消息后,向appclient发送消息RegisteredApplication,监听任务运行状态,然后调用schedule()方法
  5. 在schedule()方法中调用startExecutorOnWorks()方法,在worker上调度和启动executor,在此方法中计算每个worker上可用的资源,并且分配每个worker上需要启动的资源,调用allocateWorkerResourceExecutor方法启动executor
  6. allocateWorkerResourceExecutor方法中,调用lauchExecutor()方法,启动executor
  7. 向worker发送消息,启动executor,向appclient发送消息,改变executor的状态

    简单Spark源码分析_第5张图片

你可能感兴趣的:(Young)