大数据Spark YarnCluster模式源码分析——提交任务(图文并茂)

写在前面的话:本篇博客为原创,认真阅读需要比对spark 2.1.1的源码,预计阅读耗时30分钟,如果大家发现有问题或者是不懂的,欢迎讨论
欢迎关注公众号:后来X

spark 2.1.1的源码包(有需要自取):关注公众号【后来X】,回复spark源码

第一次写博客,写的有啥问题,欢迎大家留言评论,一定每周更新,哈哈!

今天主要分析的是spark的YarnCluster模式下的提交任务的源码,那么我们先看一下流程图
在这里插入图片描述
开始啃源码吧,为了啃源码更高效,希望大家把这张流程图搭配着一起看,可以时刻知道现在到哪一步了。

正式开始源码分析

Spark-submit命令

说到提交任务,不管是什么spark的哪种运行模式,提交任务的命令都少不了Spark-submit,下面以提交wordCount的项目的命令为例:

bin/spark-submit \
--class com.later.WordCount \
--master yarn \
--deploy-mode cluster \
./test/jars/spark-WordCount.jar \
10

那我们提交完之后,都会有一个spark-submit的线程,所以在spark源码中,double shift我们先找到SparkSubmit.scala

  1. 先找到main方法,并且提交参数的 .action 默认为submit,所以匹配到提交作业的命令:submit(appArgs)
    找到main方法

  2. 准备提交job的环境:prepareSubmitEnvironment(args)
    准备提交环境
    在这个里面,主要是对参数的赋值,我们额外注意childMainClass,通过ctrl+F搜索,发现:
    cluster模式->childMainClass = “org.apache.spark.deploy.yarn.Client”
    client模式->childMainClass = “com.later.WordCount”

  3. 最后doRunMain(),点进去
    在这里插入图片描述

  4. 判断代理是否为null,无论是if还是else,都执行
    runMain(childArgs, childClasspath, sysProps, childMainClass, args.verbose)
    在这里插入图片描述

  5. 在这里发现:定义了一个mainClass对象,并把上面第2步拿到的childMainClass赋给了mainClass
    在这里插入图片描述

  6. 并且往下滑,发现还通过反射的方式获得mainClass中的main方法,赋给了mainMethod
    在这里插入图片描述

  7. 将mainClass中的main方法当做自己的方法调用(回调)
    在这里插入图片描述
    此时的mainClass对象为:org.apache.spark.deploy.yarn.Client

yarnClient的启动

因为在上一次submit最终回调的是这个Client里面的main方法,所以double shift找到org.apache.spark.deploy.yarn.Client

  1. 找到main方法,并且创建了Client,执行了run方法
    在这里插入图片描述

  2. 向ResourceManager提交申请,获取appID,点进去
    在这里插入图片描述

  3. 既然提出申请,那就需要
    **创建申请: ** val newApp = yarnClient.createApplication()
    创建该申请的响应: val newAppResponse = newApp.getNewApplicationResponse()
    设置启动AM的环境:
    val appContext = createApplicationSubmissionContext(newApp, containerContext)
    在这里插入图片描述

  4. 这是设置适当的上下文来启动AM,也就是封装命令的具体内容 :
    val containerContext = createContainerLaunchContext(newAppResponse)
    那么既然要启动AM,就需要有相应的参数,在该方法中点进去,可以看到:javaOpts+=内存,GC,日志
    并且获取到了val userClass = 我们在提交任务的时候,–class 之后提交的参数,例如“com.later.wordCount”,并且还拿到了amClass
    cluster->val amClass = “org.apache.spark.deploy.yarn.ApplicationMaster”
    client->amClass=“org.apache.spark.deploy.yarn.ExecutorLauncher”
    在这里插入图片描述
    AM的命令:val commands =
    /bin/java “org.apache.spark.deploy.yarn.ApplicationMaster” --class WordCount…

  5. 接着第3步往下,看到了提交命令:yarnClient.submitApplication(appContext)
    在这里插入图片描述
    到此,Client已经向RM提交了申请,由RM指定一个NM来执行封装的命令,启动AM

ApplicationMaster的启动

所以我们接下来的代码应该从上面的command中:org.apache.spark.deploy.yarn.ApplicationMaster

  1. 先找到main方法,那既然是来启动AM的,所以就先创建一个AM,并且执行了master.run()
    在这里插入图片描述

  2. 接下来看run方法,大多数都是变量的赋值,其中包括创建HDFS文件系统:val fs = FileSystem.get(yarnConf)
    在这里插入图片描述

  3. 并且找到Driver的执行:runDriver(securityMgr)
    在这里插入图片描述

  4. 在Driver方法中,启动了用户类线程:userClassThread = startUserApplication()
    在这里插入图片描述

  5. 用户类线程中:用类加载器的方式来加载用户类的main方法,并且,为这个线程设置名称为"Driver",验证了在yarn的cluster模式下,Driver运行在集群(在client模式下,Driver运行在客户端)
    在这里插入图片描述

  6. 如图第4步中,除了用户类线程,还有向RM注册AM

  7. 现在有了AM,得需要向RM申请资源:allocator.allocateResources(),这里的方法名是分配资源:为RM为AM分配资源,也就是我说的申请资源
    在这里插入图片描述

  8. 既然申请资源,肯定得获取资源容器, 判断申请到的资源容器大小是不是大于0,也就是说如果RM没资源了,返回的肯定是个空的容器,如果>0,就进行处理这些资源:
    在这里插入图片描述

  9. 对获取到的资源进行分类(同一机架还是什么情况)
    在这里插入图片描述

  10. 启动runAllocatedContainers(containersToUse),就是在这个Container里面运行ExecutorBackend
    在这里插入图片描述

  11. 遍历可用的资源容器,对每一个进行如下操作:
    for (container <- containersToUse) {
    launcherPool.execute{new ExecutorRunnable().run()},找到了run方法
    在这里插入图片描述

  12. 真正启动Container
    在这里插入图片描述

  13. 那startContainer()这个启动方法进去,看一下是怎么启动的
    ctx对命令进行了设置,ctx.setCommands(commands.asJava)
    并且让NMClient开始运行 容器:nmClient.startContainer(container.get, ctx)
    在这里插入图片描述
    其中的准备命令为:val commands = prepareCommand(),点进去发现和之前的Client中的第4步有点类似。
    在这里插入图片描述
    命令是这样的:
    /bin/java org.apache.spark.executor.CoarseGrainedExecutorBackend

以上是Yarn Cluster模式下,从Spark-submit提交任务开始,到Excutor执行的全过程
那我们再次返回来看这张流程图,是不是觉得前面的部分已经比较熟悉了。
下一篇我们能继续看ExecutorBackend以及任务的划分,下一篇再见。

最后再来一波,喜欢我的欢迎点赞,欢迎关注我的公众号:后来X,回复:spark源码,获取spark2.1.1源码包

持续更新,未完待续!

发布了5 篇原创文章 · 获赞 1 · 访问量 564

猜你喜欢

转载自blog.csdn.net/weixin_38586230/article/details/104342440