将Spark添加到Spark作业 – spark-submit

确实…已经讨论了很多。

然而,这里有很多不明确的地方,并提供了一些答案,包括在jar / executor / driverconfiguration或选项中复制jar引用。

含糊和/或省略的细节

在含糊不清之后,应该为每个选项澄清不清楚和/或省略的细节:

  • ClassPath如何受到影响
    • 司机
    • 执行器(用于运行任务)
    • 一点也不
  • 分隔字符:逗号,冒号,分号
  • 如果提供的文件是自动分发的
    • 对于任务(对每个执行者)
    • 对于远程驱动程序(如果以群集模式运行)
  • 接受的URItypes:本地文件,hdfs,http等
  • 如果复制一个普通的位置,该位置是(hdfs,本地?)

它影响的选项:

  1. --jars
  2. SparkContext.addJar(...)方法
  3. SparkContext.addFile(...)方法
  4. --conf spark.driver.extraClassPath=...--driver-class-path ...
  5. --conf spark.driver.extraLibraryPath=...--driver-library-path ...
  6. --conf spark.executor.extraClassPath=...
  7. --conf spark.executor.extraLibraryPath=...
  8. 不要忘记,spark-submit的最后一个参数也是一个.jar文件。

我知道我在哪里可以find主要的火花文档 ,特别是如何提交 ,可用的选项 ,以及JavaDoc 。 不过这对我来说还是有一些漏洞,尽pipe也有部分回答。

我希望这不是那么复杂,有人可以给我一个清晰而简洁的答案。

如果我从文档中猜测,似乎是--jars ,而SparkContext addJaraddFile方法是自动分配文件的方法,而其他选项只是修改ClassPath。

假设为了简单起见,我可以同时使用3个主要选项来添加额外的应用程序jar文件:

 spark-submit --jar additional1.jar,additional2.jar \ --driver-library-path additional1.jar:additional2.jar \ --conf spark.executor.extraLibraryPath=additional1.jar:additional2.jar \ --class MyClass main-application.jar 

find一个很好的文章上的另一个post的答案 。 然而没有什么新的了解 海报对本地驱动程序(纱线客户端)和远程驱动程序(纱线群集)之间的区别做了很好的说明。 记住绝对重要。

类path。

ClassPath受影响取决于您提供的内容。 有几种方法可以在类path上设置一些东西:

  • spark.driver.extraClassPath或它的别名--driver-class-path在运行该驱动程序的节点上设置额外的类path。
  • spark.executor.extraClassPath在Worker节点上设置额外的类path。

如果你想让一个JAR在主人和工人身上都能生效,你必须在BOTH标记中分别指定这些JAR。

分离字符:

遵循与JVM相同的规则 :

  • Linux:冒号:
    • 例如:– --conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar:/opt/prog/aws-java-sdk-1.10.50.jar"
  • Windows:分号;
    • 例如:– --conf "spark.driver.extraClassPath=/opt/prog/hadoop-aws-2.7.1.jar;/opt/prog/aws-java-sdk-1.10.50.jar"

文件分发:

这取决于你正在运行你的工作的模式:

  1. 客户端模式 – Spark启动Netty HTTP服务器,该服务器在启动时为每个工作节点分配文件。 你可以看到,当你开始你的Spark作业:

     16/05/08 17:29:12 INFO HttpFileServer: HTTP File server directory is /tmp/spark-48911afa-db63-4ffc-a298-015e8b96bc55/httpd-84ae312b-5863-4f4c-a1ea-537bfca2bc2b 16/05/08 17:29:12 INFO HttpServer: Starting HTTP Server 16/05/08 17:29:12 INFO Utils: Successfully started service 'HTTP file server' on port 58922. 16/05/08 17:29:12 INFO SparkContext: Added JAR /opt/foo.jar at http://***:58922/jars/com.mycode.jar with timestamp 1462728552732 16/05/08 17:29:12 INFO SparkContext: Added JAR /opt/aws-java-sdk-1.10.50.jar at http://***:58922/jars/aws-java-sdk-1.10.50.jar with timestamp 1462728552767 
  2. 集群模式 – 在集群模式下,spark会select一个领导者工作者节点来执行驱动程序进程。 这意味着作业不是直接从主节点运行。 在这里,Spark 不会设置HTTP服务器。 您必须通过HDFS / S3 /其他所有节点可用的源手动将JARS提供给所有工作者节点。

接受的URI的文件

在“提交应用程序”中 ,Spark文档在解释文件接受的前缀方面做得很好:

当使用spark-submit时,应用程序jar以及–jars选项中包含的任何jar将自动转移到集群。 Spark使用以下URLscheme来允许传播jar子的不同策略:

  • 文件: – 绝对path和文件:/ URI由驱动程序的HTTP文件服务器提供,每个执行程序从驱动程序HTTP服务器中提取文件。
  • hdfs :, http :, https:,ftp: – 这些从预期的URI中下拉文件和JAR
  • 本地: – 以local:/开头的URI预期作为每个工作节点上的本地文件存在。 这意味着不会产生networkingIO,对于推送给每个工作者的大型文件/ JAR,或者通过NFS,GlusterFS等进行共享

请注意,JAR和文件被复制到执行程序节点上的每个SparkContext的工作目录。

如上所述,JAR被复制到每个Worker节点的工作目录中。 那到底是哪里? 通常/var/run/spark/work ,你会看到它们是这样的:

 drwxr-xr-x 3 spark spark 4096 May 15 06:16 app-20160515061614-0027 drwxr-xr-x 3 spark spark 4096 May 15 07:04 app-20160515070442-0028 drwxr-xr-x 3 spark spark 4096 May 15 07:18 app-20160515071819-0029 drwxr-xr-x 3 spark spark 4096 May 15 07:38 app-20160515073852-0030 drwxr-xr-x 3 spark spark 4096 May 15 08:13 app-20160515081350-0031 drwxr-xr-x 3 spark spark 4096 May 18 17:20 app-20160518172020-0032 drwxr-xr-x 3 spark spark 4096 May 18 17:20 app-20160518172045-0033 

而当你在里面看,你会看到你部署的所有JAR:

 [*@*]$ cd /var/run/spark/work/app-20160508173423-0014/1/ [*@*]$ ll total 89988 -rwxr-xr-x 1 spark spark 801117 May 8 17:34 awscala_2.10-0.5.5.jar -rwxr-xr-x 1 spark spark 29558264 May 8 17:34 aws-java-sdk-1.10.50.jar -rwxr-xr-x 1 spark spark 59466931 May 8 17:34 com.mycode.code.jar -rwxr-xr-x 1 spark spark 2308517 May 8 17:34 guava-19.0.jar -rw-r--r-- 1 spark spark 457 May 8 17:34 stderr -rw-r--r-- 1 spark spark 0 May 8 17:34 stdout 

受影响的选项:

要理解的最重要的事情是优先 。 如果您通过代码传递任何属性,将优先于您通过spark-submit指定的任何选项。 这在Spark文档中提到:

指定为标志或属性文件中的任何值都将传递给应用程序,并与通过SparkConf指定的那些值合并。 直接在SparkConf上设置的属性具有最高优先级 ,然后将标志传递给spark-submit或spark-shell,然后selectspark-defaults.conf文件中的选项

所以请确保你在适当的地方设置了这些值,所以当你优先于另一个时,你不会感到惊讶。

让我们分析一下每个选项:

  • --jars vs SparkContext.addJar :这些是相同的,只有一个通过spark提交,一个通过代码设置。 select一个更适合你的套房。 需要注意的一点是,使用这两个选项中的任何一个都不会将JAR添加到您的驱动程序/执行程序类path中 ,您需要使用extraClassPathconfiguration将它们显式添加到两者中。
  • SparkContext.addJar vs SparkContext.addFile :当你有一个需要与你的代码一起使用的依赖项时使用前者。 当你只是想传递一个任意的文件到你的工作节点时,使用后者,这不是代码中的运行时依赖。
  • --conf spark.driver.extraClassPath=...--driver-class-path :这些是别名,你select哪一个
  • --conf spark.driver.extraLibraryPath=..., or --driver-library-path ...与上面相同,别名。
  • --conf spark.executor.extraClassPath=... :当你有一个不能被包含在uber JAR中的依赖时使用它(例如,因为库版本之间有编译时间冲突),你需要加载哪个在运行时。
  • --conf spark.executor.extraLibraryPath=...这是作为JVM的java.library.path选项传递的。 当需要JVM可见的库path时使用它。

假设为了简单起见,我可以同时使用3个主要选项来添加额外的应用程序jar文件:

您可以安全地假设这只适用于客户端模式,而不是群集模式。 正如我以前所说。 另外,你给的例子有一些冗余的论点。 例如,将JAR传递给--driver-library-path是无用的,如果你希望它们在你的类path上,你需要将它们传递给extraClassPath 。 最终,当您在驱动程序和工作者上部署外部JAR时,您想要执行的操作是:

 spark-submit --jars additional1.jar,additional2.jar \ --driver-class-path additional1.jar:additional2.jar \ --conf spark.executor.extraClassPath=additional1.jar:additional2.jar \ --class MyClass main-application.jar 

spark 2.1.0另一种方法是在spark-submit期间使用--conf spark.driver.userClassPathFirst=true ,这会改变依赖负载的优先级,从而改变spark-job的行为,优先考虑用户的jar正在使用--jars选项添加到类path中。