博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spark配置&启动脚本分析
阅读量:5789 次
发布时间:2019-06-18

本文共 9681 字,大约阅读时间需要 32 分钟。

hot3.png

今天想停止spark集群,发现执行stop-all.sh的时候spark的相关进程都无法停止。提示:

no org.apache.spark.deploy.master.Master to stop

no org.apache.spark.deploy.worker.Worker to stop

上网查了一些资料,再翻看了一下stop-all.sh,stop-master.sh,stop-slaves.sh,spark-daemon.sh,spark-daemons.sh等脚本,发现很有可能是由于$SPARK_PID_DIR的一个环境变量导致。

1. 原因分析

我搭建的是2.6.0+Spark1.1.0+Yarn的集群。Spark、Hadoop和Yarn的停止,都是通过一些xxx.pid文件来操作的。以spark的stop-master为例,其中停止语句如下:

再查看spark-daemon.sh中的操作:

$SPARK_PID_DIR中存放的pid文件中,就是要停止进程的pid。其中$SPARK_PID_DIR默认是在系统的/tmp目录:

系统每隔一段时间就会清除/tmp目录下的内容。到/tmp下查看一下,果然没有相关进程的pid文件了。这才导致了stop-all.sh无法停止集群。

2. 停止Spark集群

担心使用kill强制停止spark相关进程会破坏集群,因此考虑回复/tmp下的pid文件,再使用stop-all.sh来停止集群。

分析spark-daemon.sh脚本,看到pid文件命名规则如下:

pid=$SPARK_PID_DIR/spark-$SPARK_IDENT_STRING-$command-$instance.pid

其中

$SPARK_PID_DIR是/tmp

$SPARK_IDENT_STRING是登录用户$USER,我的集群中用户名是cdahdp

$command是调用spark-daemon.sh时的参数,有两个:

org.apache.spark.deploy.master.Master

org.apache.spark.deploy.worker.Worker

$instance也是调用spark-daemon.sh时的参数,我的集群中是1

因此pid文件名如下:

/tmp/spark-cdahdp-org.apache.spark.deploy.master.Master-1.pid

/tmp/spark-cdahdp-org.apache.spark.deploy.worker.Worker-1.pid

通过jps查看相关进程的pid:

 

将pid保存到对应的pid文件即可。

之后调用spark的stop-all.sh,即可正常停止spark集群。

3. 停止Hadoop和Yarn集群

停止hadoop和yarn集群时,调用stop-all.sh,也会出现这个现象。其中NameNode,SecondaryNameNode,DataNode,NodeManager,ResourceManager等就是hadoop和yarn的相关进程,stop时由于找不到pid导致无法停止。分析方法同spark,对应pid文件名不同而已。

Hadoop的pid命名规则:

pid=$HADOOP_PID_DIR/hadoop-$HADOOP_IDENT_STRING-$command.pid

pid文件名:

/tmp/hadoop-cdahdp-namenode.pid

/tmp/hadoop-cdahdp-secondarynamenode.pid

/tmp/hadoop-cdahdp-datanode.pid

Yarn的pid命名规则:

pid=$YARN_PID_DIR/yarn-$YANR_IDENT_STRING-$command.pid

pid文件名:

/tmp/yarn-cdahdp-resourcemanager.pid

/tmp/yarn-cdahdp-nodemanager.pid

恢复这些pid文件即可使用stop-all.sh停止hadoop和yarn进程。

4. 根治方案

要根治这个问题,只需要在集群所有节点都设置$SPARK_PID_DIR, $HADOOP_PID_DIR和$YARN_PID_DIR即可。

修改hadoop-env.sh,增加:

export HADOOP_PID_DIR=/home/ap/cdahdp/app/pids

修改yarn-env.sh,增加:

export YARN_PID_DIR=/home/ap/cdahdp/app/pids

修改spark-env.sh,增加:

export SPARK_PID_DIR=/home/ap/cdahdp/app/pids

启动集群以后,查看/home/ap/cdahdp/app/pids目录,如下:

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.templatesbin/├── 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.shbin/├── beeline├── load-spark-env.sh├── pyspark├── run-example├── spark-class├── sparkR├── spark-shell├── spark-sql└── spark-submit0 directories, 38 files

2 分析

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

2.1 服务启动脚本分析

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

# start-master.sh1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录2.设置CLASS="org.apache.spark.deploy.master.Master"3.如果参数结尾包含--help或者-h则打印帮助信息,并退出4.设置ORIGINAL_ARGS为所有参数5.执行${SPARK_HOME}/sbin/spark-config.sh6.执行${SPARK_HOME}/bin/load-spark-env.sh7.SPARK_MASTER_PORT为空则赋值70778.SPARK_MASTER_HOST为空则赋值本主机名(hostname)9.SPARK_MASTER_WEBUI_PORT为空则赋值808010.执行脚本:"${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.sh1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录2.export SPARK_CONF_DIR,SPARK_CONF_DIR存在就用此目录,不存在用${SPARK_HOME}/conf3.export PYTHONPATH="${SPARK_HOME}/python:${PYTHONPATH}"4.export PYTHONPATH="${SPARK_HOME}/python/lib/py4j-0.10.1-src.zip:${PYTHONPATH}"# load-spark-env.sh1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录2.判断SPARK_ENV_LOADED是否有值,没有将其设置为14.设置user_conf_dir为SPARK_CONF_DIR或SPARK_HOME/conf3.执行"${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.sh1.参数个数小于等于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=110.判断SPARK_LOG_DIR是否有值,没有将其设置为${SPARK_HOME}/logs,并创建改目录,测试创建文件,修改权限11.判断SPARK_PID_DIR是否有值,没有将其设置为/tmp12.设置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.Master16.研究spark-class脚本# spark-class1.判断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_CLASSPATH7.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.sh1.判断SPARK_HOME是否有值,没有将其设置为当前文件所在目录的上级目录2.执行${SPARK_HOME}/sbin/spark-config.sh,见上述分析3.执行${SPARK_HOME}/bin/load-spark-env.sh,见上述分析4.SPARK_MASTER_PORT为空则设置为70775.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.sh1.判断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:70777.SPARK_WORKER_WEBUI_PORT为空则设置为80818.函数start_instance,略过9.判断SPARK_WORKER_INSTANCES(可以认为是单节点Worker进程数)是否为空    为空,则start_instance 1 "$@"    不为空,则循环          for ((i=0; i<$SPARK_WORKER_INSTANCES; i++)); do            start_instance $(( 1 + $i )) "$@"          done10.转向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:707711.代码再次转向spark-daemon.sh,见上诉分析分析完了master和slaves,分析下start-all.sh# start-all.sh1.判断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.sh1.判断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.sh1.判断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-examplesparkRspark-shell             ===>  spark-submit  ===>  spark-classspark-sql

3 小结

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

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

转载于:https://my.oschina.net/hblt147/blog/2875614

你可能感兴趣的文章
商教助手!解析夏普液晶高清宽屏投影机系列
查看>>
云南去年有望实现151万贫困人口净脱贫
查看>>
Java架构师面试题系列整理(大全)
查看>>
延伸产业链 中国产粮大省向“精深”问发展
查看>>
消费贷用户70%月收入低于5000元 80、90后是主要人群
查看>>
2018年内蒙古外贸首次突破1000亿元
查看>>
CTOR有助于BCH石墨烯技术更上一层楼
查看>>
被遗忘的CSS
查看>>
Webpack中的sourcemap以及如何在生产和开发环境中合理的设置sourcemap的类型
查看>>
做完小程序项目、老板给我加了6k薪资~
查看>>
java工程师linux命令,这篇文章就够了
查看>>
关于React生命周期的学习
查看>>
webpack雪碧图生成
查看>>
搭建智能合约开发环境Remix IDE及使用
查看>>
Spring Cloud构建微服务架构—服务消费基础
查看>>
RAC实践采坑指北
查看>>
runtime运行时 isa指针 SEL方法选择器 IMP函数指针 Method方法 runtime消息机制 runtime的使用...
查看>>
LeetCode36.有效的数独 JavaScript
查看>>
Scrapy基本用法
查看>>
PAT A1030 动态规划
查看>>