Spark 版本:1.3

调用shell, spark-submit.sh args[]

首先是进入 org.apache.spark.deploy.SparkSubmit 类中
调用他的 main() 方法

  1. def main(args: Array[String]): Unit = {
  2. //
  3. val appArgs = new SparkSubmitArguments(args)
  4. if (appArgs.verbose) {
  5. printStream.println(appArgs)
  6. }
  7. appArgs.action match {
  8. case SparkSubmitAction.SUBMIT => submit(appArgs)
  9. case SparkSubmitAction.KILL => kill(appArgs)
  10. case SparkSubmitAction.REQUEST_STATUS => requestStatus(appArgs)
  11. }
  12. }

  


1.1 val appArgs = new SparkSubmitArguments(args)  /*在SparkSubmitArguments(args)中获取到提交参数并进行一些初始化,*/
  """将我们手动写出的args赋值到 SparkSubmitArguments 的各个变量中"""
  parseOpts(args.toList)
  """将没有写出的args通过默认文件赋值为默认变量"""
  mergeDefaultSparkProperties()
  """使用`sparkProperties`映射和env vars来填充任何缺少的参数"""
  loadEnvironmentArguments() 此时将 action:SparkSubmitAction = Option(action).getOrElse(SUBMIT) """也就是说在没有指定action 的情况下默认为 SUBMIT"""
  validateArguments() """确保存在必填字段。 只有在加载所有默认值后才调用此方法。"""

1.2 if (appArgs.verbose) {

  printStream.println(appArgs)

  }

  """如果我们手动写出了verbose参数为true 则打印如下的变量信息"""
  """master deployMode executorMemory executorCores totalExecutorCores propertiesFile driverMemory driverCores
  driverExtraClassPath driverExtraLibraryPath driverExtraJavaOptions supervise queue numExecutors files pyFiles
  archives mainClass primaryResource name childArgs jars packages packagesExclusions repositories verbose"""

1.3 appArgs.action match {case SparkSubmitAction.SUBMIT => submit(appArgs)...}
  """匹配action的值(其实是个枚举类型的匹配), 匹配 SparkSubmitAction.SUBMIT 执行submit(appArgs)"""


2.1 submit(args: SparkSubmitArguments)

  1. /**
  2. * Submit the application using the provided parameters.
  3. *
  4. * This runs in two steps. First, we prepare the launch environment by setting up
  5. * the appropriate classpath, system properties, and application arguments for
  6. * running the child main class based on the cluster manager and the deploy mode.
  7. * Second, we use this launch environment to invoke the main method of the child
  8. * main class.
  9. */
  10. private[spark] def submit(args: SparkSubmitArguments): Unit = {
  11. val (childArgs, childClasspath, sysProps, childMainClass) = prepareSubmitEnvironment(args)
  12.  
  13. def doRunMain(): Unit = {
  14. if (args.proxyUser != null) {
  15. val proxyUser = UserGroupInformation.createProxyUser(args.proxyUser,
  16. UserGroupInformation.getCurrentUser())
  17. try {
  18. proxyUser.doAs(new PrivilegedExceptionAction[Unit]() {
  19. override def run(): Unit = {
  20. runMain(childArgs, childClasspath, sysProps, childMainClass, args.verbose)
  21. }
  22. })
  23. } catch {
  24. case e: Exception =>
  25. // Hadoop's AuthorizationException suppresses the exception's stack trace, which
  26. // makes the message printed to the output by the JVM not very helpful. Instead,
  27. // detect exceptions with empty stack traces here, and treat them differently.
  28. if (e.getStackTrace().length == 0) {
  29. printStream.println(s"ERROR: ${e.getClass().getName()}: ${e.getMessage()}")
  30. exitFn()
  31. } else {
  32. throw e
  33. }
  34. }
  35. } else {
  36. runMain(childArgs, childClasspath, sysProps, childMainClass, args.verbose)
  37. }
  38. }

使用提供的参数提交申请。这分两步进行。

"""首先,我们通过设置适当的类路径,系统属性和应用程序参数来准备启动环境,以便 根据 集群管理器 和 部署 模式运行子主类。"""

"""其次,我们使用此启动环境来调用子主类的main方法。"""

val (childArgs, childClasspath, sysProps, childMainClass) = prepareSubmitEnvironment(args) //为变量赋值

在独立群集模式下,有两个提交网关:
  (1)传统的Akka网关使用 o.a.s.deploy.Client 作为包装器(wrapper)
  (2)Spark 1.3中引入的基于REST的新网关

后者是Spark 1.3的默认行为,但如果主端点不是REST服务器,Spark提交将故障转移以使用旧网关。

根据他的部署模式来运行或者(failOver重设参数并重新提交) 之后执行 doRunMain()方法

2.1.1 doRunMain()
  其中如果有proxyUser属性则去获取他的代理对象调用proxyUser的 runMain(...)方法, 没有则直接运行 runMain(childArgs, childClasspath, sysProps, childMainClass, args.verbose)
2.2 def runMain(childArgs: Seq[String],childClasspath: Seq[String],sysProps: Map[String, String],childMainClass: String,verbose: Boolean):Unit
"""使用提供的启动环境运行子类的main方法。 请注意,如果我们正在运行集群部署模式或python应用程序,则此主类将不是用户提供的类。"""

  Thread.currentThread.setContextClassLoader(loader) 给当前线程设置一个Context加载器(loader)
  for (jar <- childClasspath) { addJarToClasspath(jar, loader) } 将childClasspath的各个类加载,实际上是调用的 loader.addURL(file.toURI.toURL) 方法
  for ((key, value) <- sysProps) {System.setProperty(key, value) } 将各个系统参数变量设置到系统中
  mainClass: Class[_] = Class.forName(childMainClass, true, loader) 使用loader将我们写的主类加载 利用反射的方法加载主类
val mainMethod = mainClass.getMethod("main", new Array[String](0).getClass) 加载mainMethod,并在接下来的代码中对它做检查,
  必须是static~("The main method in the given main class must be static")

mainMethod.invoke(null, childArgs.toArray)
到此为止启动我们的主类的main方法!!!

Spark-源码-Spark-Submit 任务提交的更多相关文章

  1. Spark源码分析之五:Task调度(一)

    在前四篇博文中,我们分析了Job提交运行总流程的第一阶段Stage划分与提交,它又被细化为三个分阶段: 1.Job的调度模型与运行反馈: 2.Stage划分: 3.Stage提交:对应TaskSet的 ...

  2. Spark源码分析之二:Job的调度模型与运行反馈

    在<Spark源码分析之Job提交运行总流程概述>一文中,我们提到了,Job提交与运行的第一阶段Stage划分与提交,可以分为三个阶段: 1.Job的调度模型与运行反馈: 2.Stage划 ...

  3. Spark 源码浅读-SparkSubmit

    Spark 源码浅读-任务提交SparkSubmit main方法 main方法主要用于初始化日志,然后接着调用doSubmit方法. override def main(args: Array[St ...

  4. Spark 源码解析:TaskScheduler的任务提交和task最佳位置算法

    上篇文章<  Spark 源码解析 : DAGScheduler中的DAG划分与提交 >介绍了DAGScheduler的Stage划分算法. 本文继续分析Stage被封装成TaskSet, ...

  5. Spark源码分析之四:Stage提交

    各位看官,上一篇<Spark源码分析之Stage划分>详细讲述了Spark中Stage的划分,下面,我们进入第三个阶段--Stage提交. Stage提交阶段的主要目的就一个,就是将每个S ...

  6. spark 源码分析之十九 -- Stage的提交

    引言 上篇 spark 源码分析之十九 -- DAG的生成和Stage的划分 中,主要介绍了下图中的前两个阶段DAG的构建和Stage的划分. 本篇文章主要剖析,Stage是如何提交的. rdd的依赖 ...

  7. Spark源码分析:多种部署方式之间的区别与联系(转)

    原文链接:Spark源码分析:多种部署方式之间的区别与联系(1) 从官方的文档我们可以知道,Spark的部署方式有很多种:local.Standalone.Mesos.YARN.....不同部署方式的 ...

  8. Spark源码分析 -- TaskScheduler

    Spark在设计上将DAGScheduler和TaskScheduler完全解耦合, 所以在资源管理和task调度上可以有更多的方案 现在支持, LocalSheduler, ClusterSched ...

  9. Spark源码分析 – DAGScheduler

    DAGScheduler的架构其实非常简单, 1. eventQueue, 所有需要DAGScheduler处理的事情都需要往eventQueue中发送event 2. eventLoop Threa ...

  10. spark 源码分析之四 -- TaskScheduler的创建和启动过程

    在 spark 源码分析之二 -- SparkContext 的初始化过程 中,第 14 步 和 16 步分别描述了 TaskScheduler的 初始化 和 启动过程. 话分两头,先说 TaskSc ...

随机推荐

  1. jquery简介(一)

    摘要:简要介绍jquery的起源,以及为什么需要使用jquery. jquery的优点 jquery体量小,加载速度快,其本身具有的功能使JavaScript应用程序开发人员的工作变得分外轻松.其中最 ...

  2. Nginx+Tomcat在Windows下做负载均衡

    一. 为什么需要对Tomcat服务器做负载均衡 Tomcat服务器作为一个Web服务器,其并发数在300-500之间,如果有超过500的并发数便会出现Tomcat不能响应新的请求的情况,严重影响网站的 ...

  3. ORACLE_DELETE

    SQL DELETE Statement The SQL DELETE Statement The DELETE statement is used to delete existing record ...

  4. scrum和团队合作

    一. 队名及宣言 队名 the better for you 宣言Change our lives with code 二. 队员及分工 a.承担软件工程的角色 姓名 学号 角色 张美庆 B20150 ...

  5. n对mod求模整除时转化成mod的数学式

    n对mod求模,它的值在0到mod-1之间,如果要求模整除的时候转化成mod可以用下面的式子: n = (n - 1 % mod + mod) % mod +1 这里先减一,模上mod再加一,这样如果 ...

  6. cs229 斯坦福机器学习笔记(一)-- 入门与LR模型

    版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn.net/Dinosoft/article/details/34960693 前言 说到机器学习,非常多人推荐的学习资 ...

  7. 【[SDOi2012]Longge的问题】

    求\(\sum_{i=1}^ngcd(i,n)\) 考虑枚举\(gcd\),现在答案变成这样 \(\sum_{d|n}d*f(d)\) \(f(d)=\sum_{i=1}^n [gcd(i,n)==d ...

  8. 【luogu P1801 黑匣子_NOI导刊2010提高(06)】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1801 替罪羊树吼啊! #include <cstdio> #include <cstrin ...

  9. Android学习笔记_22_服务Service应用之—与Activity进行相互通信的本地服务

    一.启动服务的两种方法方法: 第一种:  startService()和stopService()启动关闭服务.适用于服务和Activity之间没有调用交互的情况.如果相互之间需要方法调用或者传递参数 ...

  10. block与inline,inline和inline-block,块级和行内元素,行内替换和行内非替换元素

    block:块级元素默认display属性为block:无论块内内容有多少,总是占满一行: inline:行内元素默认display属性为inline:只占据块内的内容的大小,不会占满一整行: inl ...