本文檔基於Spark2.0,對spark啓動腳本進行分析。
date:2016/8/3
author:wangxljava
咱們主要關注3類文件,配置文件,啓動腳本文件以及自帶shell。python
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
咱們依據集羣構建步驟,先分析集羣服務腳本,從中穿插配置文件,最後分析自帶shell執行流程。linux
咱們以部署standalone,而且支持ON YARN,爲例,啓動集羣使用到start-master.sh和start-slaves.sh兩個腳本(腳本再也不貼出)。web
# 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,略
主要腳本關係以下:sql
run-example sparkR spark-shell ===> spark-submit ===> spark-class spark-sql
啓動腳本的分析,有助於理解運行時依賴關係,腳本做以下:docker
1.初始化運行時變量,配置系統參數 2.加載依賴包,運行java實例