Spark配置&啟動腳本分析


本文檔基於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實例


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM