在Spark的bin目录下的spark-submit脚本用于提交一个任务到集群中。因为是针对所有的集群管理器统一接口(local,Standalone,yarn,mesos),所以不必为每一个集群管理器进行特殊的配置。
一,打包应用的依赖
如果你的代码依赖于其它工程,你需要将它们和你的应用一起打包,目的是将这些代码分发到Spark集群中去。为了达到这个目的,需要创建一个assembly jar或者super jar,这个jar要同时包含你的代码和它的依赖。Sbt和maven都有assembly 插件。在创建assembly jar的时候,将Spark和Hadoop列为provided依赖。这些不需要进行打包,因为在运行的时候集群管理器能够提供这些jar。
对于python工程,你可以用spark-submit的--py-files参数,将.py,.zip或者.egg文件随你的应用分发到集群中。如果你依赖很多pyhon 文件建议将它们打包成.zip或者.egg文件。
二,用spark-submit提交你的应用
一旦应用打包号以后,就可以用spark-submit脚本去提交它。该脚本负责设置spark和它依赖的Classpath,支持多种集群管理器和部署模式:
./bin/spark-submit \
--class <main-class> \
--master <master-url> \
--deploy-mode <deploy-mode> \
--conf <key>=<value> \
... # other options
<application-jar> \
[application-arguments]
一些公用的选项解释:
1),--class:你主函数的入口
2),--master:cluster集群管理器
3),--deploy-mode:client或者cluster,默认是client。
4),--conf:key=value格式的spark配置。
5),application-jar:指定你jar的路径。URL必须在集群中任何节点都能找到,如在hdfs://path 或者file://path(此路径必须在所有节点都存在)
6),application-arguments:你应用程序入口main函数的参数。
一个通用的部署策略是在一个集群入口机器上提交你的程序到集群(比如,在EC2集群中的master节点)。在这种设置中,client模式是合适的。在client模式下,driver和spark-submit运行在同一进程,扮演者集群客户端的角色。输入和输出的应用连接到控制台。因此,这种模式特别适合类似spark-shell的涉及REPL的应用程序。
另外,如果你的应用程序需要从非集群机器,比如你的笔记本,提交到集群,建议使用cluster模式,最小化减少driver和Executor之间的网络延迟。当前,Standalone模式下并不支持python应用以cluster模式运行。
对于python的应用程序,简单用.py文件代替<application-jar>,然后通过--py-files将.zip,,egg,.py文件传添加进去。
也有一些参数是指定集群管理器特有的。比如,对于Standalone集群的cluster模式下,通过指定--supervise参数,可以以让driver在异常退出的时候自动重启。可以通过spark-submit --help查看更多的参数。举一些例子:
# Run application locally on 8 cores
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master local[8] \
/path/to/examples.jar \
100
# Run on a Spark standalone cluster in client deploy mode
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://207.184.161.138:7077 \
--executor-memory 20G \
--total-executor-cores 100 \
/path/to/examples.jar \
1000
# Run on a Spark standalone cluster in cluster deploy mode with supervise
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://207.184.161.138:7077 \
--deploy-mode cluster \
--supervise \
--executor-memory 20G \
--total-executor-cores 100 \
/path/to/examples.jar \
1000
# Run on a YARN cluster
export HADOOP_CONF_DIR=XXX
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \ # can be client for client mode
--executor-memory 20G \
--num-executors 50 \
/path/to/examples.jar \
1000
# Run a Python application on a Spark standalone cluster
./bin/spark-submit \
--master spark://207.184.161.138:7077 \
examples/src/main/python/pi.py \
1000
# Run on a Mesos cluster in cluster deploy mode with supervise
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master mesos://207.184.161.138:7077 \
--deploy-mode cluster \
--supervise \
--executor-memory 20G \
--total-executor-cores 100 \
http://path/to/examples.jar \
1000
三,master URLs
master可以是以下几种:
Master URL | 含义 |
---|---|
local | Spark单线程本地跑 |
local[K] | Spark K个工作线程本地跑 |
local[K,F] | K个工作线程,F次失败尝试 |
local[*] | Cup核数个工作线程,本地 |
local[*,F] | Cup核数个工作线程,F次失败尝试 |
spark://HOST:PORT | Standalone cluster master |
spark://HOST1:PORT1,HOST2:PORT2 | 基于zk做了HA |
mesos://HOST:PORT | Mesos cluster. |
yarn | 基于yarn的client或者cluster模式 |
四,从一个file中加载配置
Spark-Submit脚本可以从配置文件中加载spark默认配置,然后将它们传递给你的应用程序。默认情况下会从conf/spark-defaults.conf读取。
Spark默认配置的优先级是SparkConf设置的,spark-submit设置的,然后是默认配置文件读取的。
假如你对配置属性的来源不清晰,可以在运行spark-submit的时候指定--verbose参数来输出详细的调试信息。
五,高级依赖管理
当使用spark-submit,用户的jar和--jars选项指定的jar会被自动传输到集群。--jars参数指定URLs必须用逗号分隔,该列表包含在driver和Executor Classpath上。 目录不适用于--jars。Spark使用以下URL方案来允许不同的策略来传播jar:
1,file:-绝对路径和file:/ URIs,被http 文件服务器管理,每个Executor都可以从http server拉去指定的文件。
2,hdfs:,http:,https:,ftp:- 按照期望的方式从URI指定的位置去下载files和jars
3,local:- 以local:/开头的URI,需要在所有的worker节点上都存在,意味着没有网络IO发生,所以这种方式对大的files和jars很适合,也可以通过NFS,GlusterFS等共享。
注意,JARS和files会被拷贝到Executor的工作目录。这将会浪费很大的磁盘空间,使用完了需要进行clean up。针对yarn模式下,cleanup是自动处理的,对于SparkStandalone模式下,自动cleanup需要配置spark.worker.cleanup.appDataTtl参数。
也可以使用maven来管理依赖,用--packages参数,然后依赖以逗号分隔。所有的传递依赖将使用此命令时进行处理。可以使用--repositories参数将另外的repositories 或者SBT的resolvers依赖以逗号分割的方式加入。(请注意,在某些情况下,可以在repository URI中提供受密码保护的存储库的凭据,例如https:// user:password @ host / ....在以这种方式提供凭据时请小心。)。这些命令可以是 与pyspark,spark-shell和spark-submit一起使用。
六,总结
本文主要讲如何提交一个用户的应用提交的集群,重点是要搞清楚依赖是如何被提交的集群的。至于依赖是如何被程序加载执行的请看浪尖的第一份视频,关于spark driver和Executor运行环境的讲解。能搞明白这些,才算真正搞明白spark的精髓。