本文档基于Spark2.0,对spark启动脚本进行分析。

date:2016/8/3

author:wangxl

Spark配置&启动脚本分析

我们主要关注3类文件,配置文件,启动脚本文件以及自带shell。

1 文件概览

conf/
├── docker.properties.template
├── fairscheduler.xml.template
├── log4j.properties.template
├── metrics.properties.template
├── slaves.template
├── spark-defaults.conf.template
└── spark-env.sh.template
sbin/
├── slaves.sh
├── spark-config.sh
├── spark-daemon.sh
├── spark-daemons.sh
├── start-all.sh
├── start-history-server.sh
├── start-master.sh
├── start-mesos-dispatcher.sh
├── start-mesos-shuffle-service.sh
├── start-shuffle-service.sh
├── start-slave.sh
├── start-slaves.sh
├── start-thriftserver.sh
├── stop-all.sh
├── stop-history-server.sh
├── stop-master.sh
├── stop-mesos-dispatcher.sh
├── stop-mesos-shuffle-service.sh
├── stop-shuffle-service.sh
├── stop-slave.sh
├── stop-slaves.sh
└── stop-thriftserver.sh
bin/
├── beeline
├── load-spark-env.sh
├── pyspark
├── run-example
├── spark-class
├── sparkR
├── spark-shell
├── spark-sql
└── spark-submit 0 directories, 38 files

2 分析

我们依据集群构建步骤,先分析集群服务脚本,从中穿插配置文件,最后分析自带shell执行流程。

2.1 服务启动脚本分析

我们以部署standalone,并且支持ON YARN,为例,启动集群使用到start-master.sh和start-slaves.sh两个脚本(脚本不再贴出)。

# start-master.sh
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.设置CLASS="org.apache.spark.deploy.master.Master"
3.如果参数结尾包含--help或者-h则打印帮助信息,并退出
4.设置ORIGINAL_ARGS为所有参数
5.执行${SPARK_HOME}/sbin/spark-config.sh
6.执行${SPARK_HOME}/bin/load-spark-env.sh
7.SPARK_MASTER_PORT为空则赋值7077
8.SPARK_MASTER_HOST为空则赋值本主机名(hostname)
9.SPARK_MASTER_WEBUI_PORT为空则赋值8080
10.执行脚本:
"${SPARK_HOME}/sbin"/spark-daemon.sh start $CLASS 1 \
--host $SPARK_MASTER_HOST --port $SPARK_MASTER_PORT --webui-port $SPARK_MASTER_WEBUI_PORT \
$ORIGINAL_ARGS
其中10肯定是重点,分析之前我们看看5,6都干了些啥,最后直译出最后一个脚本
# spark-config.sh
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.export SPARK_CONF_DIR,SPARK_CONF_DIR存在就用此目录,不存在用${SPARK_HOME}/conf
3.export PYTHONPATH="${SPARK_HOME}/python:${PYTHONPATH}"
4.export PYTHONPATH="${SPARK_HOME}/python/lib/py4j-0.10.1-src.zip:${PYTHONPATH}"
# load-spark-env.sh
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.判断SPARK_ENV_LOADED是否有值,没有将其设置为1
4.设置user_conf_dir为SPARK_CONF_DIR或SPARK_HOME/conf
3.执行"${user_conf_dir}/spark-env.sh" [注:set -/+a含义再做研究]
4.选择scala版本,2.10和2.11都存在的情况下,优先选择2.11
# spark-env.sh
列举很多种模式的选项配置,以YARN client mode为例
# Options read in YARN client mode
# - HADOOP_CONF_DIR, to point Spark towards Hadoop configuration files
# - SPARK_EXECUTOR_INSTANCES, Number of executors to start (Default: 2)
# - SPARK_EXECUTOR_CORES, Number of cores for the executors (Default: 1).
# - SPARK_EXECUTOR_MEMORY, Memory per Executor (e.g. 1000M, 2G) (Default: 1G)
# - SPARK_DRIVER_MEMORY, Memory for Driver (e.g. 1000M, 2G) (Default: 1G)
回过头来看看需要直译出的最后一个脚本,如下:
sbin/spark-daemon.sh start org.apache.spark.deploy.master.Master 1 --host hostname --port 7077 --webui-port 8080
上面搞了半天只是设置了变量,最终才进入主角,继续分析spark-daemon.sh脚本
# spark-daemon.sh
1.参数个数小于等于1,打印帮助
2.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
3.执行${SPARK_HOME}/sbin/spark-config.sh,见上述分析 [类似脚本是否有重复?原因是有的人是直接用spark-daemon.sh启动的服务,反正重复设置下变量不需要什么代价]
4.判断第一个参数是否是--config,如果是取空格后一个字符串,然后判断该目录是否存在,不存在则打印错误信息并退出,存在设置SPARK_CONF_DIR为该目录,shift到下一个参数[注:--config只能用在第一参数上]
5.分别设置option、command、instance为后面的三个参数(如:option=start,command=org.apache.spark.deploy.master.Master,instance=1)[注:很多人用spark-daemon.sh启动服务不成功的原因是名字不全]
6.日志回滚函数,主要耕宇更改日志名,如log-->log.1等,略过
7.执行${SPARK_HOME}/bin/load-spark-env.sh,见上述分析
8.判断SPARK_IDENT_STRING是否有值,没有将其设置为$USER(linux用户)
9.设置SPARK_PRINT_LAUNCH_COMMAND=1
10.判断SPARK_LOG_DIR是否有值,没有将其设置为${SPARK_HOME}/logs,并创建改目录,测试创建文件,修改权限
11.判断SPARK_PID_DIR是否有值,没有将其设置为/tmp
12.设置log和pid
log="$SPARK_LOG_DIR/spark-$SPARK_IDENT_STRING-$command-$instance-$HOSTNAME.out"
pid="$SPARK_PID_DIR/spark-$SPARK_IDENT_STRING-$command-$instance.pid"
13.判断SPARK_NICENESS是否有值,没有将其设置为0 [注:调度优先级,见后面]
14.定义run_command()函数,暂且略过,调用时再作分析
15.进入case语句,判断option值,进入该分支,我们以start为例
执行run_command class "$@",其中$@此时为空,经验证,启动带上此参数后,关闭也需,不然关闭不了,后面再分析此参数作用
我们正式进入run_command()函数,分析
I.设置mode=class,创建SPARK_PID_DIR,上面的pid文件是否存在,
II.SPARK_MASTER不为空,同步删除某些文件
III.回滚log日志
IV.进入case,command=org.apache.spark.deploy.master.Master,最终执行
nohup nice -n "$SPARK_NICENESS" "${SPARK_HOME}"/bin/spark-class $command "$@" >> "$log" 2>&1 < /dev/null &
newpid="$!"
echo "$newpid" > "$pid"
重点转向bin/spark-class org.apache.spark.deploy.master.Master
16.研究spark-class脚本
# spark-class
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.执行${SPARK_HOME}/bin/load-spark-env.sh,见上述分析
3.判断JAVA_HOME是否为NULL,不是则设置RUNNER="${JAVA_HOME}/bin/java",否则找系统自带,在没有则报未设置,并退出
4.查找SPARK_JARS_DIR,若${SPARK_HOME}/RELEASE文件存在,则SPARK_JARS_DIR="${SPARK_HOME}/jars",否则SPARK_JARS_DIR="${SPARK_HOME}/assembly/target/scala-$SPARK_SCALA_VERSION/jars"
5.若SPARK_JARS_DIR不存在且$SPARK_TESTING$SPARK_SQL_TESTING有值[注:一般我们不设置这两变量],报错退出,否则LAUNCH_CLASSPATH="$SPARK_JARS_DIR/*"
6.SPARK_PREPEND_CLASSES不是NULL,则LAUNCH_CLASSPATH="${SPARK_HOME}/launcher/target/scala-$SPARK_SCALA_VERSION/classes:$LAUNCH_CLASSPATH",添加编译相关至LAUNCH_CLASSPATH
7.SPARK_TESTING不是NULL,则unset YARN_CONF_DIR和unset HADOOP_CONF_DIR,暂且当做是为了某种测试
8.build_command函数,略过
9.最终调用"$RUNNER" -Xmx128m -cp "$LAUNCH_CLASSPATH" org.apache.spark.launcher.Main "$@",直译:java -Xmx128m -cp "$LAUNCH_CLASSPATH" org.apache.spark.launcher.Main "$@"
10.转向java类org.apache.spark.launcher.Main,这就是java入口类,有机会再做分析 分析完了master,我们再来分析slaves
# start-slaves.sh
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.执行${SPARK_HOME}/sbin/spark-config.sh,见上述分析
3.执行${SPARK_HOME}/bin/load-spark-env.sh,见上述分析
4.SPARK_MASTER_PORT为空则设置为7077
5.SPARK_MASTER_HOST为空则设置为`hostname`
6.启动slaves,
"${SPARK_HOME}/sbin/slaves.sh" cd "${SPARK_HOME}" \; "${SPARK_HOME}/sbin/start-slave.sh" "spark://$SPARK_MASTER_HOST:$SPARK_MASTER_PORT"
遍历conf/slaves中主机,其中有设置SPARK_SSH_OPTS,ssh每一台机器执行"${SPARK_HOME}/sbin/start-slave.sh" "spark://$SPARK_MASTER_HOST:$SPARK_MASTER_PORT"
7.转向start-slave.sh
# start-slave.sh
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.设置CLASS="org.apache.spark.deploy.worker.Worker"
3.如果参数结尾包含--help或者-h则打印帮助信息,并退出
4.执行${SPARK_HOME}/sbin/spark-config.sh,见上述分析
5.执行${SPARK_HOME}/bin/load-spark-env.sh,见上述分析
6.MASTER=$1,这里MASTER=spark://hostname:7077,然后shift,也就是说单独启动单个slave使用start-slave.sh spark://hostname:7077
7.SPARK_WORKER_WEBUI_PORT为空则设置为8081
8.函数start_instance,略过
9.判断SPARK_WORKER_INSTANCES(可以认为是单节点Worker进程数)是否为空
为空,则start_instance 1 "$@"
不为空,则循环
for ((i=0; i<$SPARK_WORKER_INSTANCES; i++)); do
start_instance $(( 1 + $i )) "$@"
done
10.转向start_instance函数
设置WORKER_NUM=$1
"${SPARK_HOME}/sbin"/spark-daemon.sh start $CLASS $WORKER_NUM \
--webui-port "$WEBUI_PORT" $PORT_FLAG $PORT_NUM $MASTER "$@"
直译:spark-daemon.sh start org.apache.spark.deploy.worker.Worker 1 --webui-port 7077 spark://hostname:7077
11.代码再次转向spark-daemon.sh,见上诉分析 分析完了master和slaves,分析下start-all.sh
# start-all.sh
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.执行${SPARK_HOME}/sbin/spark-config.sh,见上述分析
3.执行"${SPARK_HOME}/sbin"/start-master.sh,见上诉分析
4.执行"${SPARK_HOME}/sbin"/start-slaves.sh,见上诉分析 还剩下start-history-server.sh、start-shuffle-service.sh和start-thriftserver.sh
# start-history-server.sh
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.执行${SPARK_HOME}/sbin/spark-config.sh,见上述分析
3.执行${SPARK_HOME}/bin/load-spark-env.sh,见上述分析
4.exec "${SPARK_HOME}/sbin"/spark-daemon.sh start org.apache.spark.deploy.history.HistoryServer 1 $@ ,见上诉分析
# start-shuffle-service.sh
1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录
2.执行${SPARK_HOME}/sbin/spark-config.sh,见上述分析
3.执行${SPARK_HOME}/bin/load-spark-env.sh,见上述分析
4.exec "${SPARK_HOME}/sbin"/spark-daemon.sh start org.apache.spark.deploy.ExternalShuffleService 1 ,见上诉分析
# start-thriftserver.sh 开启thriftserver,略

2.2 自带各种shell分析

主要脚本关系如下:

run-example
sparkR
spark-shell ===> spark-submit ===> spark-class
spark-sql

3 小结

启动脚本的分析,有助于理解运行时依赖关系,脚本作如下:

1.初始化运行时变量,配置系统参数
2.加载依赖包,运行java实例

Spark配置&启动脚本分析的更多相关文章

  1. HBase配置&启动脚本分析

    本文档基于hbase-0.96.1.1-cdh5.0.2,对HBase配置&启动脚本进行分析 date:2016/8/4 author:wangxl HBase配置&启动脚本分析 剔除 ...

  2. Hadoop启动脚本分析

    Hadoop启动脚本分析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 能看到这篇博客的你估计对Hadoop已经有一个系统的了解了,最起码各种搭建方式你应该是会的,不会也没有关系, ...

  3. 4. hadoop启动脚本分析

    4. hadoop启动脚本分析 1. hadoop的端口 ``` 50070 //namenode http port 50075 //datanode http port 50090 //2name ...

  4. hadoop启动脚本分析及常见命令

    进程------------------ [hdfs]start-dfs.sh NameNode NN DataNode DN SecondaryNamenode 2NN [yarn]start-ya ...

  5. busybox rootfs 启动脚本分析(二)

    上次分析了busybox的启动脚本,这次分析一下init.d中一些脚本的内容. 参考链接 http://www.cnblogs.com/helloworldtoyou/p/6169678.html h ...

  6. busybox rootfs 启动脚本分析(一)

    imx6文件系统启动脚本分析.开机运行/sbin/init,读取/etc/inittab文件,进行初始化. 参考链接 http://blog.163.com/wghbeyond@126/blog/st ...

  7. Hadoop 2.0+YARN启动脚本分析与实战经验

    start-all.sh脚本现在已经废弃,推荐使用start-dfs.sh和start-yarn.sh分别启动HDFS和YARN. 在新一代的Hadoop里面HDFS称为了统一存储的平台,而YARN成 ...

  8. Jenkins|简单Job配置|启动脚本|测试报告

    目录 1.Jenkins安装 2.Jenkins启动脚本 3.节点配置 4.任务配置 5.集成HTML测试报告 1.Jenkins安装 操作环境:Ubuntu jenkins针对windows,ubu ...

  9. Hadoop 启动脚本分析与实战经验

    start-all.sh脚本现在已经废弃,推荐使用start-dfs.sh和start-yarn.sh分别启动HDFS和YARN. 在新一代的Hadoop里面HDFS称为了统一存储的平台,而YARN成 ...

随机推荐

  1. GDB调试一

    http://blog.csdn.net/haoel/article/details/2881 GDB主要调试的是C/C++的程序.要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行 ...

  2. Longest Palindromic Substring -LeetCode

    题目 Given a string s,find the longest palindromic substring in S.You may assume  that the maximum len ...

  3. ORACLE 数据库概述

    1,发展史: 1978年,Orcale诞生 1982年,Orcale3推出了,它是第一个能够运行在大型机和小型机上的关系型数据库 1997年,Orcale公司推出了基于java语言的Orcale8,并 ...

  4. Win7中,取消共享文件夹后有个小锁

    用过windows7的朋友都知道,Windows 7 中设置某一个文件夹属性为共享后,文件夹的图标上就增加一个小锁图案.起到了一个标记作用,挺好的.但是即使你将该文件夹的共享功能取消后,该小锁图案还是 ...

  5. CSU 1335 高桥和低桥

    开始队友说是线段树,看了看貌似也是,上手敲了个嵌套的线段树,O(nlognlogn)的复杂度果断tle了 TAT 思路:对h[i]排序,对每次涨水退水,先用二分查找,再用一个数组保存当前点之后所有点被 ...

  6. ftp二进制与ascii传输方式区别

    ASCII 和BINARY模式区别:    用HTML 和文本编写的文件必须用ASCII模式上传,用BINARY模式上传会破坏文件,导致文件执行出错.    BINARY模式用来传送可执行文件,压缩文 ...

  7. ubuntu及终端快捷键

    1.关于终端的快捷键: Tab:tab键是比较常用的一个快捷键,它的作用是补全文件名或者路径.举例 来说,输入”cd /ho”在按一下tab键,终端里就会显示”cd /home”了.如果您的文件夹下, ...

  8. mysql 命令行 自动补全

    配置文件中 默认关闭自动补全: [mysql] #no-auto-rehash # faster start of mysql but no tab completition 改为: [mysql] ...

  9. hdu 3461 Code Lock

    http://acm.hdu.edu.cn/showproblem.php?pid=3461 并差集和幂取模 这道题主要是求不可操作区间. #include <cstdio> #inclu ...

  10. C51工具是怎么进行覆盖分析的

    C51工具针对8051微控制器的有限存储器资源进行了优化设计. 为了最有效地利用存储器,根据一个很容易解释的方法,自动变量和函数参数在存储器中均进行覆盖处理. 首先,连接器根据源程序生成调用树.例如: ...