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

时间:2016-05-10 08:03:01

标签: java scala apache-spark jar spark-submit

是的......已经讨论了很多。

然而,有很多歧义和一些答案提供...包括在jar / executor / driver配置或选项中复制jar引用。

含糊不清和/或省略的细节

对于每个选项,应澄清含糊不清,不清楚和/或省略的细节:

  • ClassPath如何受到影响
    • 驱动程序
    • 执行人员(针对正在运行的任务)
    • 两个
    • 根本不是
  • 分隔字符:逗号,冒号,分号
  • 如果提供的文件是自动分发的
    • 用于任务(对每个执行者)
    • 用于远程驱动程序(如果以群集模式运行)
  • 接受的URI类型:本地文件,hdfs,http等
  • 如果将复制到一个公共位置,该位置是(hdfs,local?)

它影响的选项:

  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文件。
  9. 我知道在哪里可以找到main spark documentation,特别是how to submitoptions可用,还有JavaDoc。然而,这对我来说仍然有一些漏洞,尽管它也有部分回答。

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

    如果我从文档中猜测,似乎--jarsSparkContext 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
    

    an answer to another posting上发现了一篇很好的文章。然而没有什么新学到的海报确实很好地评论了本地驱动程序(纱线客户端)和远程驱动程序(纱线群集)之间的区别。记住这一点非常重要。

6 个答案:

答案 0 :(得分:139)

类路径:

ClassPath会受到影响,具体取决于您提供的内容。有几种方法可以在类路径上设置一些东西:

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

如果您希望在Master和Worker上同时使用某个JAR,则必须在BOTH标志中单独指定它们。

分离字符:

Following the same rules as the 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选择了一个领导者工作节点来执行驱动程序进程。这意味着作业不直接从主节点运行。在这里,Spark 不会设置HTTP服务器。您必须通过HDFS / S3 /所有节点可用的其他来源手动使JARS可供所有工作节点使用。

  3. 文件的接受URI

    "Submitting Applications"中,Spark文档很好地解释了文件的已接受前缀:

      

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

         
        
    • file: - 绝对路径和文件:/ URI由驱动程序的HTTP提供   文件服务器,每个执行程序从驱动程序HTTP中提取文件   服务器。
    •   
    • hdfs:,http:,https:,ftp: - 这些下拉文件和JAR   来自URI的预期
    •   
    • local: - 以local:/开头的URI   期望在每个工作节点上作为本地文件存在。这意味着   不会产生网络IO,适用于大型文件/ 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文档中提到:

      

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

    因此,请确保将这些值设置在适当的位置,这样当一个人优先于另一个时,你不会感到惊讶。

    让我们分析每个有问题的选项:

    • --jars vs SparkContext.addJar:这些是相同的,只有一个是通过spark提交设置的,另一个是通过代码设置的。选择最适合你的那个。需要注意的一件重要事情是,使用其中任何一个选项都不会将JAR添加到您的驱动程序/执行程序类路径,您需要使用extraClassPath配置明确添加它们两者。
    • SparkContext.addJar vs SparkContext.addFile:当您拥有需要与代码一起使用的依赖关系时,请使用前者。当您只想将任意文件传递给工作节点时,请使用后者,这不是代码中的运行时依赖性。
    • --conf spark.driver.extraClassPath=...--driver-class-path:这些是别名,不管你选择哪一个
    • --conf spark.driver.extraLibraryPath=..., or --driver-library-path ...与上述相同,别名。
    • --conf spark.executor.extraClassPath=...:如果您有一个不能包含在超级JAR中的依赖项(例如,因为库版本之间存在编译时冲突)并且您需要在运行时加载它
    • --conf spark.executor.extraLibraryPath=...这是作为JVM的java.library.path选项传递的。当您需要JVM可见的库路径时,请使用此选项。
      

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

    您可以安全地假设这只适用于客户端模式,而不是群集模式。正如我之前所说的那样。此外,您给出的示例有一些冗余的参数。例如,将JAR传递给--driver-library-path是没用的,如果您希望将它们放在类路径上,则需要将它们传递给extraClassPath。最终,当您在驱动程序和worker上部署外部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
    

答案 1 :(得分:4)

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

答案 2 :(得分:3)

将spark-submit与--master yarn-cluster一起使用时,应用程序jar以及--jars选项随附的所有jar都会自动传输到集群。 --jars之后提供的URL必须用逗号分隔。该列表包含在驱动程序和执行程序的类路径中

示例:

spark-submit --master yarn-cluster --jars ../lib/misc.jar,../lib/test.jar --class MainClass MainApp.jar

https://spark.apache.org/docs/latest/submitting-applications.html

答案 3 :(得分:0)

使用--jars有限制:如果要为jar/xml文件的位置指定目录,则不允许目录扩展。这意味着如果您需要为每个jar指定绝对路径。

如果指定--driver-class-path并且您正在纱线群集模式下执行,则驱动程序类不会更新。我们可以在选项卡环境下验证spark ui或spark history server下的类路径是否更新。

对我来说,传递包含目录扩展且在纱线群集模式下工作的jar的选项是--conf选项。最好将驱动程序和执行程序类路径作为--conf传递,这会将它们添加到spark会话对象本身,并且这些路径会反映在Spark Configuration上。但请确保将jar放在群集中的相同路径上。

spark-submit \
  --master yarn \
  --queue spark_queue \
  --deploy-mode cluster    \
  --num-executors 12 \
  --executor-memory 4g \
  --driver-memory 8g \
  --executor-cores 4 \
  --conf spark.ui.enabled=False \
  --conf spark.driver.extraClassPath=/usr/hdp/current/hbase-master/lib/hbase-server.jar:/usr/hdp/current/hbase-master/lib/hbase-common.jar:/usr/hdp/current/hbase-master/lib/hbase-client.jar:/usr/hdp/current/hbase-master/lib/zookeeper.jar:/usr/hdp/current/hbase-master/lib/hbase-protocol.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/scopt_2.11-3.3.0.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/spark-examples_2.10-1.1.0.jar:/etc/hbase/conf \
  --conf spark.hadoop.mapred.output.dir=/tmp \
  --conf spark.executor.extraClassPath=/usr/hdp/current/hbase-master/lib/hbase-server.jar:/usr/hdp/current/hbase-master/lib/hbase-common.jar:/usr/hdp/current/hbase-master/lib/hbase-client.jar:/usr/hdp/current/hbase-master/lib/zookeeper.jar:/usr/hdp/current/hbase-master/lib/hbase-protocol.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/scopt_2.11-3.3.0.jar:/usr/hdp/current/spark2-thriftserver/examples/jars/spark-examples_2.10-1.1.0.jar:/etc/hbase/conf \
  --conf spark.hadoop.mapreduce.output.fileoutputformat.outputdir=/tmp

答案 4 :(得分:0)

虽然我们使用spark-submit实用工具提交spark作业,但是有一个选项--jars。使用此选项,我们可以将jar文件传递给Spark应用程序。

答案 5 :(得分:0)

与jar和类路径有关的其他可配置Spark选项,在部署模式为yarn的情况下如下所示
从spark文档中,

spark.yarn.jars

List of libraries containing Spark code to distribute to YARN containers.
By default, Spark on YARN will use Spark jars installed locally, but the Spark jars can also be
in a world-readable location on HDFS. This allows YARN to cache it on nodes so that it doesn't
need to be distributed each time an application runs. To point to jars on HDFS, for example,
set this configuration to hdfs:///some/path. Globs are allowed.

spark.yarn.archive

    An archive containing needed Spark jars for distribution to the YARN cache. If set, this
configuration replaces spark.yarn.jars and the archive is used in all the
application's containers. The archive should contain jar files in its root directory.
Like with the previous option, the archive can also be hosted on HDFS to speed up file
distribution.

用户可以配置此参数以指定其jar,然后将其包含在Spark驱动程序的类路径中。