spark都進化到2.0了,雖然以前對spark有所瞭解但總感受似懂非懂的,因此想花時間看看源碼。java
面對大量的源碼從哪裏着手呢,想到老子的一句話「天下難事必做於易,天下大事必做於細」,因此就從腳本部分來啃。python
因本人腳本編程能力也並非那麼強,因此在總結的時候會穿插一些shell的東西。此處只介紹shell腳本,不涉及bat腳本。sql
先按照首字母順序介紹下每一個腳本的功能:shell
spark-1.5.0/binapache
beeline:基於SQLLine CLI的JDBC客戶端,能夠鏈接到hive,操做hive中的數據。編程
load-spark-env.sh:導入conf目錄下的spark-env.sh文件。windows
pyspark:python調用spark.bash
run-example:運行examples目錄下的示例。dom
spark-class:調用org.apache.spark.launcher.Main, 多被其餘腳本調用。函數
spark-shell:spark shell交互腳本。
spark-sql:spark sql運行腳本。
spark-submit:spark做業提交腳本。
sparkR:R語言調用spark。
再介紹下腳本之間的調用關係:
[注]箭頭所指方向爲被依賴或被引用的腳本
部分腳本解析:
spark-calss部分代碼:
# The launcher library will print arguments separated by a NULL character, to allow arguments with # characters that would be otherwise interpreted by the shell. Read that in a while loop, populating # an array that will be used to exec the final command. CMD=() while IFS= read -d '' -r ARG; do CMD+=("$ARG") done < <("$RUNNER" -cp "$LAUNCH_CLASSPATH" org.apache.spark.launcher.Main "$@")
exec "${CMD[@]}"
註解:對比以前版本的腳本,如今的腳本簡化了不少東西,好多判斷都移動到了java或scala代碼內。下一步就是分析org.apache.spark.launcher.Main 這個類。
spark-shell 代碼:
#!/usr/bin/env bash # Shell script for starting the Spark Shell REPL #驗證是不是cygwin cygwin=false case "`uname`" in CYGWIN*) cygwin=true;; esac # 開啓posix模式 set -o posix #獲取父級目錄的絕對路徑,$0爲當前腳本名 export FWDIR="$(cd "`dirname "$0"`"/..; pwd)" export _SPARK_CMD_USAGE="Usage: ./bin/spark-shell [options]" #手動添加 -Dscala.usejavacp=true,scala 默認不會使用 java classpath SPARK_SUBMIT_OPTS="$SPARK_SUBMIT_OPTS -Dscala.usejavacp=true" #腳本入口,實際調用的是spark-submit腳本 function main() { if $cygwin; then stty -icanon min 1 -echo > /dev/null 2>&1 export SPARK_SUBMIT_OPTS="$SPARK_SUBMIT_OPTS -Djline.terminal=unix" "$FWDIR"/bin/spark-submit --class org.apache.spark.repl.Main --name "Spark shell" "$@" stty icanon echo > /dev/null 2>&1 else export SPARK_SUBMIT_OPTS "$FWDIR"/bin/spark-submit --class org.apache.spark.repl.Main --name "Spark shell" "$@" fi } # Copy restore-TTY-on-exit functions from Scala script so spark-shell exits properly even in # binary distribution of Spark where Scala is not installed exit_status=127 saved_stty="" # restore stty settings (echo in particular) function restoreSttySettings() { stty $saved_stty saved_stty="" } function onExit() { if [[ "$saved_stty" != "" ]]; then restoreSttySettings fi exit $exit_status } # 中斷時進行的操做 trap onExit INT # 保存終止設置 saved_stty=$(stty -g 2>/dev/null) # clear on error so we don't later try to restore them if [[ ! $? ]]; then saved_stty="" fi #調用main函數 main "$@" # 記錄腳本退出狀態 # then reenable echo and propagate the code. exit_status=$? onExit
註解:顯然spark-shell調用的是spark-submit ,利用--class org.apache.spark.repl.Main --name "Spark shell"傳入參數。
此處本人主要對shell交互的實現比較感興趣,後續會調研下,以後研究的類天然是class org.apache.spark.repl.Main。
spark-sql代碼
export FWDIR="$(cd "`dirname "$0"`"/..; pwd)" export _SPARK_CMD_USAGE="Usage: ./bin/spark-sql [options] [cli option]" exec "$FWDIR"/bin/spark-submit --class org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver "$@"
註解:這部分腳本簡單明瞭,要調研的類也很清楚:org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver 。
spark sql雖然操做的是hive,可是比HQL快多了,基於內存的計算果斷有優點啊。
spark-submit代碼
SPARK_HOME="$(cd "`dirname "$0"`"/..; pwd)" # disable randomized hash for string in Python 3.3+ export PYTHONHASHSEED=0 exec "$SPARK_HOME"/bin/spark-class org.apache.spark.deploy.SparkSubmit "$@"
註解:不兼容python3.3+以上的版本,具體緣由不明,表示沒怎麼接觸過python。
調用spark-class實現的job提交,以何種模式提交的判斷猜想應該在org.apache.spark.deploy.SparkSubmit中。
sparkR代碼:
export SPARK_HOME="$(cd "`dirname "$0"`"/..; pwd)" source "$SPARK_HOME"/bin/load-spark-env.sh export _SPARK_CMD_USAGE="Usage: ./bin/sparkR [options]" exec "$SPARK_HOME"/bin/spark-submit sparkr-shell-main "$@"
註解:實現的方式與python相似。
shell不明點參照:
1.set -o posix
set命令是shell解釋器的一個內置命令,用來設置shell解釋器的屬性,從而可以控制shell解釋器的一些行爲。
在set命令中,選項前面跟着 - 號表示開啓這個選項, + 表示關閉這個選項。
set -o posix:開啓bash的posix模式。
2.command -v java
command [-pVv] command [arg ...]
用command指定可取消正常的shell function尋找。只有內建命令及在PATH中找獲得的纔會被執行。
"-p"選項,搜尋命令的方式是用PATH來找。"-V"或"-v"選項,會顯示出該命令的一些簡約描述。
3.[ [[ test
[ is a shell builtin
[[ is a shell keyword
test is a shell builtin
[ = test
[[ 可用 && | ,經常使用可避免錯誤。
4.read -d
-d :表示delimiter,即定界符,通常狀況下是以IFS爲參數的間隔,可是經過-d,咱們能夠定義一直讀到出現執行的字符位置。例如read –d madfds value,讀到有m的字符的時候就不在繼續向後讀,例如輸入爲 hello m,有效值爲「hello」,請注意m前面的空格等會被刪除。這種方式能夠輸入多個字符串,例如定義「.」做爲結符號等等
read命令 -n(不換行) -p(提示語句) -n(字符個數) -t(等待時間) -s(不回顯)
5.setty
stty(set tty)命令用於顯示和修改當前註冊的終端的屬性。
tty -icanon 設置一次性讀完操做,如使用getchar()讀操做,不須要按enter
stty icanon 取消上面設置
[-]icanon
enable erase, kill, werase, and rprnt special characters
6.$@
輸入參數,常與shift連用。參數較多或參數個數不肯定時可用。
總結:
shell腳本遵循簡單明瞭的原則,而對比之前的腳本也會發現這點,一些複雜的判斷邏輯大多都移入源碼裏了,例如submit腳本中運行模式的判斷,這樣會使腳本精簡不少。
bin下的腳本都以2個空格爲縮進,同一腳本中邏輯不一樣的代碼塊之間空行分隔,另有必要的註釋,風格統一。
環境變量或全局變量的引入是放在load-spark-env.sh中的,其餘腳本再以 . 的方式引入,腳本複用。
parent_dir="$(cd "`dirname "$0"`"/..; pwd)" 是一段頗有用的代碼。
命令性質的腳本統一放在了bin下,而功能性質的大多都放在了sbin下。