spark on yarn 作业提交流程源码

借图 https://blog.csdn.net/qq_40640228/article/details/128265115

脚本启动执行

脚本入口:spark-submit.sh
spark-submit.sh中调用了spark-class.sh
image.png
spark-class.sh中首先是找到java的目录,使用org.apache.spark.launcher.Main类生成执行命令,赋值到变量CMD中。使用exec执行CMD
image.png
image.png
image.png
org.apache.spark.launcher.Main
调用buildCommand函数,就是调用builder.buildCommand。builder是SparkSubmitCommandBuilder。
image.png
image.png
SparkSubmitCommandBuilder
根据参数选择java命令。调用buildSparkSubmitCommand函数
image.png
buildSparkSubmitCommand中首先调用buildJavaCommand生成xx/bin/java -cp xxx1.jar:xxx2.jar
后面加上启动类和相关参数。
最后命令:xx/bin/java -cp xxx1.jar:xxx2.jar org.apache.spark.deploy.SparkSubmit arg[0]…
image.png
image.png

SparkSubmit

可以看到是调用SparkSubmit的doSubmit方法
image.png
调用submit方法
image.png
调用runMain方法
image.png
调用prepareSubmitEnvironment获取到childArgs, childClasspath, sparkConf, childMainClass。
根据childMainClass创建SparkApplication对象,因为是yarn集群模型,所以是YarnClusterApplication
调用YarnClusterApplication的start方法。
image.png
prepareSubmitEnvironment
根据 --master yarn --deploy-mode cluster确定是isYarnCluster
childMainClass = YARN_CLUSTER_SUBMIT_CLASS
YARN_CLUSTER_SUBMIT_CLASS=“org.apache.spark.deploy.yarn.YarnClusterApplication”
image.png
image.png
image.png

YarnClusterApplication

YarnClusterApplication在resource-managers目录下面的yarn工程的org.apache.spark.deploy.yarn包下的Client类中。
start方法就是创建Client,执行run方法,调用submitApplication方法
image.png
image.png
submitApplication
1.yarnClient初始化并连接
2.yarnClient向resourceManager申请创建app
3.生成app的启动命令(启动类是ApplicationMaster)
4.app状态变更为SUBMITTED
image.png
createContainerLaunchContext
image.png
启动内存spark.driver.memory指定,默认是1G
image.png
启动类是org.apache.spark.deploy.yarn.ApplicationMaster
image.png
createApplicationSubmissionContext
指定yarn的container内存和core
image.png

ApplicationMaster

创建ApplicationMaster对象,并执行run方法。
image.png
run中获取attemptID,并启动driver(runDriver方法)
image.png

runDriver

1.调用startUserApplication执行用户类,用户类中会初始化sparkContext
2.等待sparkContext初始化完成
3.注册applicationMaster
4.申请container,用于部署executor
5.唤醒用户线程,等待用户线程执行完毕
image.png

执行用户类

startUserApplication
通过反射获取到用户类的main方法对象,并执行。
image.png
创建sparkContext
通过SparkSession创建sparkContext对象。
image.png
image.png
image.png
sparkContext初始化完成后,调用YarnClusterScheduler的postStartHook方法。
最终用户线程通知主线程sparkContext初始化完成,同时用户线程暂停,等待application向yarn申请到资源后再继续执行。
image.png
image.png
image.png
image.png

等待sc初始化

applicationMaster的host、port需要等到sparkContext初始化才有,所以在此等待。
用户类中会初始化sparkContext并通知返回sparkContext。
image.png

注册applicationMaster

创建并初始化amClient(负责AM与RM进行通信的客户端)
向rm注册am
image.png

申请container

首先创建YarnAllocator(负责跟ResourceManager申请和释放container),再申请executor对应的资源并启动。
image.png
image.png
updateResourceRequests 更新一下container的request
handleAllocatedContainers 启动成功申请下来的容器
image.png

  1. 计算还缺少的executor数量missing
  2. 将处在pending状态的request分类:
    1. localRequests 能匹配上本地
    2. staleRequests 不能匹配上本地
    3. anyHostRequests 对运行节点没有要求
  3. staleRequests匹配不上的请求移除
  4. 根据本地优先策略尽可能分配container
  5. 生成新的ContainerRequest(newLocalityRequests),如果不够的话,新增不限host不限rack的请求,多的话就移除多余的LocalityRequests
  6. addContainerRequest将请求发送给rm,等待实际分配

image.png
rm成功分配下来的container有可能存在不符合的情况。所以还要校验一遍,移除不符合的container。

  1. host匹配
  2. rack匹配
  3. 无host无rack匹配
  4. 移除不符合的container
  5. 启动container

image.png

启动container

可以看到启动container是创建ExecutorRunnable对象并调用run方法
image.png
初始化NMClient,调用startContainer方法
image.png
prepareCommand 拼接java启动命令,启动类是org.apache.spark.executor.YarnCoarseGrainedExecutorBackend
nmClient.startContainer(container.get, ctx)发送启动请求,在对应的节点启动,container中指定了节点
image.png
image.png
YarnCoarseGrainedExecutorBackend 在container中负责管理executor,是CoarseGrainedExecutorBackend的子类
可以看到是CoarseGrainedExecutorBackend的run方法中传入了YarnCoarseGrainedExecutorBackend创建的函数,在run中会创建YarnCoarseGrainedExecutorBackend。
CoarseGrainedExecutorBackend是一个RPC节点,创建的时候会调用onStart方法。
image.png
CoarseGrainedExecutorBackend向driver注册executor,注册成功向自身发送注册成功消息RegisteredExecutor
image.png
接收RegisteredExecutor消息,创建Executor,先driver发送executor加载完成消息LaunchedExecutor。Executor创建完成后,backend就会等待LaunchTask消息让executor执行task
image.png
到此container已经启动,里面的executor也准备就绪,等待task任务。

唤醒用户线程

applicationMaster的runDriver方法最后,唤醒用户线程(用户代码执行完sparkContext初始化后就暂停了,可以),继续执行用户代码。
image.png
image.png
回到用户代码,rdd部分是用户的数据逻辑,最后调用action算子(此处是collect)会开始执行job。
image.png
collect算子,最后调用的是sc的runJob方法。
image.png
image.png
启动部分就到这里吧,再后面就是task划分和task执行

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值