从源码角度看 Spark 任务提交流程(上)

本文从源码角度探讨Spark如何向Yarn提交任务,包括Spark Submit过程,Yarn Client的角色,以及任务提交的关键流程。通过分析Spark Shell命令的执行过程,解析参数封装、应用启动等步骤,揭示Spark与Yarn交互的细节。
摘要由CSDN通过智能技术生成

前言

 最近阅读一下 Spark 的部分源码,在这一过程中通过源码结合之前所了解的相关内容,能够对之前知识进行完整的梳理也能更一进步了解 Spark 运行的底层逻辑,由于阅读源码是一个较为艰深的过程遂将其记录下来方便日后回顾,本篇我们来讲一下我们的 Spark on Yarn 在提交一个任务后俩个框架为我们做了些什么。

Spark 向 Yarn 提交任务的流程

 在 Linux 上安装完 Spark 后都会用一个官方提供的 example 来测一测我们的 Spark 安装成功了,比如下面这段命令:

bin/spark-submit \
--master yarn \
./examples/jars/spark-examples_2.11-2.1.1.jar \
--class org.apache.spark.examples.SparkPi \
100

 上面命令的具体参数含义就不说了,从我们执行的 shell 名 spark-submit 就可以看出我们是在做一个提交行为,而我们又是向 Yarn 提交的任务因此我们就会得到如下的这张流程图,而本文的目的就是通过源码来看看我们的 Spark 到底是如何一步一步执行图中的步骤的,为了有助于理解我们还是先用文字略微详细的描述一下下图。

在这里插入图片描述

  1. Spark Client 将我们需要执行的应用提交给 Yarn 集群中的 RM (resource manager)
  2. RM 收到后在一台 NM (node manager) 中启动 AM (application master)
  3. AM 在计算所需要的资源后向 RM 申请资源
  4. RM 返回可用的资源列表给 AM
  5. AM 根据资源列表在相应的 NM 上启动 Container 并在其中启动 Executor
  6. Executor 向 AM 注册自己
  7. AM 将任务分解并分发给各个 executor

一般来说至此我们就大致了解了整个流程,如果你对 Yarn 很了解那么整个流程就更加明了了,因为在 Yarn 上提交任务基本都是差不多的流程,但就如开头所说我们要从源码的角度来看看究竟为啥是这些流程,因此我们可以先记住这种图再读完接下来的内容后再回过头来看看是否相符。

Spark 提交任务源码

Spark Submit

 我们本次使用的工具是 IDEA 其方便的搜索功能能够帮助我们顺畅的进行阅读,首先让我们回到开头的那个命令

bin/spark-submit \
--master yarn \
./examples/jars/spark-examples_2.11-2.1.1.jar \
--class org.apache.spark.examples.SparkPi \
100

我们执行的 shell 叫 spark-submit 当我们执行后其启动了一个进程,安装我们对于 Java 相关的知识其一定是执行了一个 main() 函数,于是我们打开这个 shell 看看其执行的是那个类,我们打开后就会发现有如下的这行代码

exec "${SPARK_HOME}"/bin/spark-class org.apache.spark.deploy.SparkSubmit "$@"

可以看到我们就找到了执行的主类org.apache.spark.deploy.SparkSubmit,就是通过它来完成我们的应用提交的,接下来我们来看看这个类中的 main() 函数做了那些事情,代码如下:

def main(args: Array[String]): Unit = {
   
    // 封装 Spark 提交参数
    val appArgs = new SparkSubmitArguments(args)
    if (appArgs.verbose) {
   
        // scalastyle:off println
        printStream.println(appArgs)
        // scalastyle:on println
    }
    appArgs.action match {
   
        // 执行提交
        case SparkSubmitAction.SUBMIT => submit(appArgs)
        case SparkSubmitAction.KILL => kill(appArgs)
        case SparkSubmitAction.REQUEST_STATUS => requestStatus(appArgs)
    }
}

比较重要的两行代码我已经注释出来了,可以看到主要是做了两件事情,1)将我们提交的参数封装成一个对象;2)将参数封装成对象后执行提交,我们先来看第一步,代码如下:

private[deploy] class SparkSubmitArguments(args: Seq[String], env: Map[String, String] = sys.env)
  extends SparkSubmitArgumentsParser {
   
  var master: String = null
  var deployMode: String = null
  var executorMemory: String = null
  var executorCores: String = null
  var totalExecutorCores: String = null
  .....
  var mainClass: String = null
  var primaryResource: String = null
  var name: String = null
  var childArgs: ArrayBuffer[String] = new ArrayBuffer[String]()
  var jars: String = null
  ......

进到 SparkSubmitArguments 这个类立马就会看到上述代码内容 (有省略),我们很快就能发现有一些变量是我们在命令行中输入的比如 master -> --master, mainClass-> --Class 可见我们在 spark-submit 后添加的参数都被封装进了这个对象中,知道了我们的参数是如何封装的之后我们就可以进入到提交了我们进入 submit 来看看其做了那些事情代码如下 (方便阅读有部分省略):

private def submit(args: SparkSubmitArguments): Unit = {
   
    // 准备提交环境
    val (childArgs, childClasspath, sysProps, childMainClass) = 			    			 												prepareSubmitEnvironment(args)
    def doRunMain(): Unit = {
   
        if (args.proxyUser != null) {
   
            ...
            try {
   
                proxyUser.doAs(new PrivilegedExceptionAction[Unit]() {
   
                    override def run(): Unit = {
   
                        // 根据提交环境运行 main 函数
                        runMain(childArgs, childClasspath, sysProps, childMainClass, 										args.verbose)
                    }
                })
            } catch {
   
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值