Spark on yarn 源码分析

Yarn-Cluster模式

Spark on yarn 源码分析_第1张图片


  1. 执行脚本提交任务,实际是启动一个 SparkSubmit 的 JVM 进程;
  2. SparkSubmit 类中的 main方法反射调用Client的main方法;
  3. Client创建Yarn客户端,然后向Yarn发送执行指令:bin/java ApplicationMaster;
  4. Yarn框架收到指令后会在指定的NM中启动ApplicationMaster;
  5. ApplicationMaster启动Driver线程,执行用户的作业;
  6. AM向RM注册,申请资源;
  7. 获取资源后AM向NM发送指令:bin/java CoarseGrainedExecutorBacken;
  8. 启动ExecutorBackend, 并向driver注册.
  9. 注册成功后, ExecutorBackend会创建一个Executor对象.
  10. Driver会给ExecutorBackend分配任务, 并监控任务的执行.
  • 注意:
    • SparkSubmit、ApplicationMaster和CoarseGrainedExecutorBacken是独立的进程;
    • Client和Driver是独立的线程;
    • Executor是一个对象。

Spark on yarn 源码分析_第2张图片
Sparksubmit阶段

  • 首先运行bin/spark-submit --master yarn --deploy-mode cluster,在bin/SparkSubmit找到SparkSubmit类,运行main方法,
  • 然后进入submit方法里,准备好提交环境(prepareSubmitEnvironment(args)),得到““org.apache.spark.deploy.yarn.Client””,
  • 运行runMain(childArgs, childClasspath, sysProps, childMainClass, args.verbose),反射Clinet类运行main方法
  • 在Client的main方法里调用run(),运行submitApplication()
  • 在submitApplication方法里初始化并启动yarn(yarnClient.start()),并且创建一个AM程序( yarnClient.createApplication())并提交到RM上
    Spark on yarn 源码分析_第3张图片
    ApplicationMaster阶段
  • 在AM的main方法里运行 ApplicationMaster 的 run 方法(master.run())
  • 在run方法里runDriver(securityMgr),启动一个子线程来执行用户类提交的 main 方法,并且讲此线程名设置为Driver,
  • 在runDriver的主线程里则注册AM到RM(registerAM),RM分配资源(handleAllocatedContainers)然后启动分配到的容器(runAllocatedContainers)
    Spark on yarn 源码分析_第4张图片
    CoarseGrainedExecutorBackend阶段
  • 运行main方法, 启动 CoarseGrainedExecutorBackend( run),然后运行onstart方法, // 向驱动注册 Executor (ref.ask)
  • Driver端的CoarseGrainedSchedulerBackend类的receiveAndReply方法收到后返回RegisteredExecutor(executorRef.send(RegisteredExecutor))
  • CoarseGrainedExecutorBackend端的receive方法接收到RegisteredExecutor创建 Executor 对象( new Executor)
  • Executor 全部创建完成后Driver开始执行main方法,遇到Action算子时会触发一个job,在一个job里会根据宽依赖进行划分stage,每一个stage生成一个taskSet,之后将task分配到各个Executor

Spark on yarn 源码分析_第5张图片

Yarn-Client模式

Spark on yarn 源码分析_第6张图片


  1. 执行脚本提交任务,实际是启动一个SparkSubmit的 JVM 进程;
  2. SparkSubmit伴生对象中的main方法反射调用用户代码的main方法;
  3. 启动Driver线程,执行用户的作业,并创建ScheduleBackend;
  4. YarnClientSchedulerBackend向RM发送指令:bin/java ExecutorLauncher;
  5. Yarn框架收到指令后会在指定的NM中启动ExecutorLauncher(实际上还是调用ApplicationMaster的main方法);
object ExecutorLauncher {

  def main(args: Array[String]): Unit = {
    ApplicationMaster.main(args)
  }

}
  1. AM向RM注册,申请资源;
  2. 获取资源后AM向NM发送指令:bin/java CoarseGrainedExecutorBacken;
  3. 后面和cluster模式一致
    注意:
  • SparkSubmit、ExecutorLauncher和CoarseGrainedExecutorBacken是独立的进程;
  • driver不是一个子线程,而是直接运行在SparkSubmit进程的main线程中, 所以sparkSubmit进程不能退出.

Spark on yarn 源码分析_第7张图片
SparkSubmit阶段

  • 当用户使用了bin/spark-submit --master yarn --deploy-mode client,在bin/spark-submit脚本的全类名,运行SparSubmit的main方法,
  • 进入main方法里,然后在进入submit方法,通过准备环境方法(prepareSubmitEnvironment)获取到childMainClass=用户提交的类,
  • 接着在submit方法里的runMain里通过反射调用用户提交类的main方法,
  • 通过实例化SparkContext,创建TaskScheduler(SparkContext.createTaskScheduler),在创建TaskScheduler方法里创建YarnClientSchedulerBackend(cm.createSchedulerBackend)
  • 在SparkContext类启动YarnScheduler(_taskScheduler.start())
  • 在YarnClientSchedulerBackend的start方法里使用 Client 提交应用bindToYarn(client.submitApplication(), None)
  • -接着在Client类里运行submitApplication方法,在createContainerLaunchContext方法里反射调用(“org.apache.spark.deploy.yarn.ExecutorLauncher”),然后提交应用到RM(yarnClient.submitApplication(appContext))

ExecutorLauncher阶段

  • 启动ExecutorLauncher,在main方法里执行 ApplicationMaster.main(args)
  • 执行ApplicationMaster 的main方法, 运行 ApplicationMaster 的 run 方法
  • 在run方法调用 runExecutorLauncher(securityMgr),在方法里执行registerAM。

你可能感兴趣的:(Spark)