《深入理解Spark:核心思想與原始碼分析》(前言及第1章)
自己犧牲了7個月的週末和下班空閒時間,通過研究Spark原始碼和原理,總結整理的《深入理解Spark:核心思想與原始碼分析》一書現在已經正式出版上市,目前亞馬遜、京東、噹噹、天貓等網站均有銷售,歡迎感興趣的同學購買。我開始研究原始碼時的Spark版本是1.2.0,經過7個多月的研究和出版社近4個月的流程,Spark自身的版本迭代也很快,如今最新已經是1.6.0。目前市面上另外2本原始碼研究的Spark書籍的版本分別是0.9.0版本和1.2.0版本,看來這些書的作者都與我一樣,遇到了這種問題。由於研究和出版都需要時間,所以不能及時跟上Spark的腳步,還請大家見諒。但是Spark核心部分的變化相對還是很少的,如果對版本不是過於追求,依然可以選擇本書。
為了讓大家對本書有個大致瞭解,這裡將本書的前言及第一章的內容附上:
前言
為什麼寫這本書
要回答這個問題,需要從我個人的經歷說起。說來慚愧,我第一次接觸計算機是在高三。當時跟大家一起去網咖玩CS,跟身邊的同學學怎麼“玩”。正是通過這種“玩”的過程,讓我瞭解到計算機並沒有那麼神祕,它也只是臺機器,用起來似乎並不比開啟電視機費勁多少。高考填志願的時候,憑著直覺“糊里糊塗”就選擇了計算機專業。等到真正學習計算機課程的時候卻又發現,它其實很難!
早在2004年,還在學校的我跟很多同學一樣,喜歡看Flash,也喜歡談論Flash甚至做Flash。感覺Flash正如它的名字那樣“閃光”。那些年,在學校裡,知道Flash的人可要比知道Java的人多得多,這說明當時的Flash十分火熱。此外Oracle也成為關係型資料庫裡的領軍人物,很多人甚至覺得懂Oracle要比懂Flash、Java及其它資料庫要厲害得多!
2007年,筆者剛剛參加工作不久。那時Struts1、Spring、Hibernate幾乎可以稱為那些用Java作為開發語言的軟體公司的三駕馬車。很快隨著Struts2的誕生,很快替代了Struts1的地位,讓我第一次意識到IT領域的技術更新竟然如此之快!隨著很多傳統軟體公司向網際網路公司轉型,更讓人吃驚的是,當初那個勇於技術更新的年輕人Gavin King,也許很難想象他創造的Hibernate也難以確保其地位,iBATIS誕生了!
2010年,有關Hadoop的技術圖書湧入中國,當時很多公司用它只是為了資料統計、資料探勘或者搜尋。一開始,人們對於Hadoop的認識和使用可能相對有限。大約2011年的時候,關於雲端計算的概念在網上吵得火熱,當時依然在做網際網路開發的我,對其只是“道聽途說”。後來跟同事借了一本有關雲端計算的書,回家挑著看了一些內容,之後什麼也沒有弄到手,悵然若失!上世紀60年代,美國的軍用網路作為網際網路的雛形,很多內容已經與雲端計算中的某些說法相類似。到上世紀80年代,網際網路就已經開啟了雲端計算,為什麼如今又要重提這樣的概念?這個問題筆者可能回答不了,還是交給歷史吧。
2012年,國內又呈現出大資料熱的態勢。從國家到媒體、教育、IT等幾乎所有領域,人人都在談大資料。我的親戚朋友中,無論老師、銷售還是工程師們都可以對大資料談談自己的看法。我也找來一些Hadoop的書籍進行學習,希望能在其中探索到大資料的味道。
有幸在工作過程中接觸到阿里的開放資料處理服務(Open Data Processing Service, 簡稱ODPS),並且基於ODPS與其他小夥伴一起構建阿里的大資料商業解決方案——御膳房。去杭州出差的過程中,有幸認識和仲,跟他學習了阿里的實時多維分析平臺——Garuda和實時計算平臺——Galaxy的部分知識。和仲推薦我閱讀Spark的原始碼,這樣會對實時計算及流式計算有更深入的瞭解。2015年春節期間,自己初次上網查閱Spark的相關資料學習,開始研究Spark原始碼。還記得那時只是出於對大資料的熱愛,想使自己在這方面的技術能力有所提升。
從閱讀Hibernate原始碼開始,到後來閱讀Tomcat、Spring的原始碼,隨著挖掘原始碼,從學習原始碼的過程中成長,我對原始碼閱讀也越來越感興趣。隨著對Spark原始碼閱讀的深入,發現很多內容從網上找不到答案,只能自己硬啃了。隨著自己的積累越來越多,突然有天發現,我所總結的這些內容好像可以寫成一本書了!從閃光(Flash)到火花(Spark),足足有11個年頭了。無論是Flash、Java,還是Spring、iBATIS我一直扮演著一個追隨者,我接受這些書籍的洗禮,從未給予。如今我也是Spark的追隨者,不同的是,我不再只想簡單的攫取,還要給予。
最後還想說下2016年是我從事IT工作的第十個年頭,此書特別作為送給自己的十週年禮物。
本書的主要特色
- 按照原始碼分析的習慣設計,從指令碼分析到初始化再到核心內容,最後介紹Spark的擴充套件內容。整個過程遵循由淺入深,由深到廣的基本思路。
- 本書涉及的所有內容都有相應的例子,以便於對原始碼的深入研究能有更好的理解。
- 本書儘可能的用圖來展示原理,加速讀者對內容的掌握。
- 本書講解的很多實現及原理都值得借鑑,能幫助讀者提升架構設計、程式設計等方面的能力。
- 本書儘可能保留較多的原始碼,以便於初學者能夠在脫離辦公環境的地方(如地鐵、公交),也能輕鬆閱讀。
本書面向的讀者
原始碼閱讀是一項苦差事,人力和時間成本都很高,尤其是對於Spark陌生或者剛剛開始學習的人來說,難度可想而知。本書儘可能保留原始碼,使得分析過程不至於產生跳躍感,目的是降低大多數人的學習門檻。如果你是從事IT工作1~3年的新人或者希望開始學習Spark核心知識的人來說,本書非常適合你。如果你已經對Spark有所瞭解或者已經使用它,還想進一步提高自己,那麼本書更適合你。
如果你是一個開發新手,對Java、Linux等基礎知識不是很瞭解的話,本書可能不太適合你。如果你已經對Spark有深入的研究,本書也許可以作為你的參考資料。 總體說來,本書適合以下人群:
- 想要使用Spark,但對Spark實現原理不瞭解,不知道怎麼學習的人;
- 大資料技術愛好者,以及想深入瞭解Spark技術內部實現細節的人;
- 有一定Spark使用基礎,但是不瞭解Spark技術內部實現細節的人;
- 對效能優化和部署方案感興趣的大型網際網路工程師和架構師;
- 開原始碼愛好者,喜歡研究原始碼的同學可以從本書學到一些閱讀原始碼的方式方法。
本書不會教你如何開發Spark應用程式,只是拿一些經典例子演示。本書會簡單介紹Hadoop MapReduce、Hadoop YARN、Mesos、Tachyon、ZooKeeper、HDFS、Amazon S3,但不會過多介紹這些等框架的使用,因為市場上已經有豐富的這類書籍供讀者挑選。本書也不會過多介紹Scala、Java、Shell的語法,讀者可以在市場上選擇適合自己的書籍閱讀。本書實際適合那些想要破解一個個潘多拉魔盒的人!
如何閱讀本書
本書分為三大部分(不包括附錄):
第一部分為準備篇(第1 ~ 2章),簡單介紹了Spark的環境搭建和基本原理,幫助讀者瞭解一些背景知識。
第二部分為核心設計篇(第3 ~ 7章),著重講解SparkContext的初始化、儲存體系、任務提交與執行、計算引擎及部署模式的原理和原始碼分析。
第三部分為擴充套件篇(第8 ~ 11章),主要講解基於Spark核心的各種擴充套件及應用,包括:SQL處理引擎、Hive處理、流式計算框架Spark Streaming、圖計算框架GraphX、機器學習庫MLlib等內容。
本書最後還添加了幾個附錄,包括:附錄A介紹的Spark中最常用的工具類Utils;附錄B是Akka的簡介與工具類AkkaUtils的介紹;附錄C為Jetty的簡介和工具類JettyUtils的介紹;附錄D為Metrics庫的簡介和測量容器MetricRegistry的介紹;附錄E演示了Hadoop1.0版本中的word count例子;附錄F 介紹了工具類CommandUtils的常用方法;附錄G是關於Netty的簡介和工具類NettyUtils的介紹;附錄H列舉了筆者編譯Spark原始碼時遇到的問題及解決辦法。
為了降低讀者閱讀理解Spark原始碼的門檻,本書儘可能保留原始碼實現,希望讀者能夠懷著一顆好奇的心,Spark當前很火熱,其版本更新也很快,本書以Spark 1.2.3版本為主,有興趣的讀者也可按照本書的方式,閱讀Spark的最新原始碼。
聯絡方式
本書內容很多,限於筆者水平有限,書中內容難免有錯誤之處。在本書出版的任何時間,如果你對本書有任何問題或者意見都可以通過郵箱[email protected]或者部落格http://www.cnblogs.com/jiaan-geng/聯絡我,給我提交你的建議或者想法,我本人將懷著一顆謙卑之心與大家共同進步。
致謝
感謝蒼天,讓我生活在這樣一個時代接觸網際網路和大資料;感謝父母,這麼多年來,在學習、工作及生活上的幫助與支援;感謝妻子在生活中的照顧和謙讓。
感謝楊福川編輯和高婧雅編輯給予本書出版的大力支援與幫助。
感謝冰夷老大和王賁老大讓我有幸加入阿里,接觸大資料應用;感謝和仲對Galaxy和Garuda耐心細緻的講解以及對Spark的推薦;感謝張中在百忙之中給本書寫評語;感謝周亮、澄蒼、民瞻、石申、清無、少俠、徵宇、三步、謝衣、曉五、法星、曦軒、九翎、峰閱、丁卯、阿末、紫丞、海炎、涵康、雲颺、孟天、零一、六仙、大知、井凡、隆君、太奇、晨炫、既望、寶升、都靈、鬼厲、歸鍾、梓撤、昊蒼、水村、惜冰、惜陌、元乾等同學在工作上的支援和幫助。
耿嘉安
北京
第1章 環境準備
“凡事豫則立,不豫則廢;言前定,則不跲;事前定,則不困;”
——《禮記·中庸》
本章導讀:
在深入瞭解一個系統的原理、實現細節之前,應當先準備好它的原始碼編譯環境、執行環境。如果能在實際環境安裝和執行Spark,顯然能夠提升讀者對於Spark的一些感受,對系統能有個大體的印象,有經驗的技術人員甚至能夠猜出一些Spark採用的程式設計模型、部署模式等。當你通過一些途徑知道了系統的原理之後,難道不會問問自己?這是怎麼做到的。如果只是遊走於系統使用、原理了解的層面,是永遠不可能真正理解整個系統的。很多IDE本身帶有除錯的功能,每當你閱讀原始碼,陷入重圍時,除錯能讓我們更加理解執行期的系統。如果沒有除錯功能,不敢想象閱讀原始碼的困難。
本章的主要目的是幫助讀者構建原始碼學習環境,主要包括以下內容:
- 在windows環境下搭建原始碼閱讀環境;
- 在Linux搭建基本的執行環境;
- Spark的基本使用,如spark-shell。
1.1 執行環境準備
考慮到大部分公司在開發和生成環境都採用Linux作業系統,所以筆者選用了64位的Linux。在正式安裝Spark之前,先要找臺好機器。為什麼?因為筆者在安裝、編譯、除錯的過程中發現Spark非常耗費記憶體,如果機器配置太低,恐怕會跑不起來。Spark的開發語言是Scala,而Scala需要執行在JVM之上,因而搭建Spark的執行環境應該包括JDK和Scala。
1.1.1 安裝JDK
使用命令getconf LONG_BIT檢視linux機器是32位還是64位,然後下載相應版本的JDK並安裝。
下載地址:
配置環境:
cd ~ vim .bash_profile
新增如下配置:
export JAVA_HOME=/opt/java export PATH=$PATH:$JAVA_HOME/bin export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
由於筆者的機器上已經安裝過openjdk,安裝命令:
$ su -c "yum install java-1.7.0-openjdk"
安裝完畢後,使用java –version命令檢視,確認安裝正常,如圖1-1所示。
圖1-1 檢視java安裝是否正常
1.1.2 安裝Scala
選擇最新的Scala版本下載,下載方法如下:
wget http://downloads.typesafe.com/scala/2.11.5/scala-2.11.5.tgz
移動到選好的安裝目錄,例如:
mv scala-2.11.5.tgz ~/install/
進入安裝目錄,執行以下命令:
chmod 755 scala-2.11.5.tgz tar -xzvf scala-2.11.5.tgz
配置環境:
cd ~ vim .bash_profile
新增如下配置:
export SCALA_HOME=$HOME/install/scala-2.11.5 export PATH=$PATH:$SCALA_HOME/bin:$HOME/bin
安裝完畢後鍵入scala,進入scala命令列,如圖1-2所示。
圖1-2 進入Scala命令列
1.1.3安裝Spark
選擇最新的Spark版本下載,下載方法如下:
wget http://archive.apache.org/dist/spark/spark-1.2.0/spark-1.2.0-bin-hadoop1.tgz
移動到選好的安裝目錄,如:
mv spark-1.2.0-bin-hadoop1.tgz~/install/
進入安裝目錄,執行以下命令:
chmod 755 spark-1.2.0-bin-hadoop1.tgz tar -xzvf spark-1.2.0-bin-hadoop1.tgz
配置環境:
cd ~ vim .bash_profile
新增如下配置:
export SPARK_HOME=$HOME/install/spark-1.2.0-bin-hadoop1
1.2 Spark初體驗
本節通過Spark的基本使用,讓讀者對Spark能有初步的認識,便於引導讀者逐步深入學習。
1.2.1 執行spark-shell
要執行spark-shell,需要先對Spark進行配置。
進入Spark的conf資料夾:
cd ~/install/spark-1.2.0-bin-hadoop1/conf
拷貝一份spark-env.sh.template,命名為spark-env.sh,對它進行編輯,命令如下:
cp spark-env.sh.template spark-env.sh vim spark-env.sh
新增如下配置:
export SPARK_MASTER_IP=127.0.0.1 export SPARK_LOCAL_IP=127.0.0.1
啟動spark-shell:
cd ~/install/spark-1.2.0-bin-hadoop1/bin ./spark-shell
最後我們會看到spark啟動的過程,如圖1-3所示:
圖1-3 Spark啟動過程
從以上啟動日誌中我們可以看到SparkEnv、MapOutputTracker、BlockManagerMaster、DiskBlockManager、MemoryStore、HttpFileServer、SparkUI等資訊。它們是做什麼的?此處望文生義即可,具體內容將在後邊的章節詳細給出。
1.2.2 執行word count
這一節,我們通過word count這個耳熟能詳的例子來感受下Spark任務的執行過程。啟動spark-shell後,會開啟Scala命令列,然後按照以下步驟輸入指令碼:
步驟1 輸入val lines = sc.textFile("../README.md", 2),執行結果如圖1-4所示。
圖1-4 步驟1執行結果
步驟2 輸入val words = lines.flatMap(line => line.split(" ")),執行結果如圖1-5所示。
圖1-5 步驟2執行結果
步驟3 輸入val ones = words.map(w => (w,1)),執行結果如圖1-6所示。
圖1-6 步驟3執行結果
步驟4 輸入val counts = ones.reduceByKey(_ + _),執行結果如圖1-7所示。
圖1-7 步驟4執行結果
步驟5 輸入counts.foreach(println),任務執行過程如圖1-8和圖1-9所示。輸出結果如圖1-10所示。
圖1-8 步驟5執行過程部分
圖1-9 步驟5執行過程部分
圖1-10 步驟5輸出結果
在這些輸出日誌中,我們先是看到Spark中任務的提交與執行過程,然後看到單詞計數的輸出結果,最後列印一些任務結束的日誌資訊。有關任務的執行分析,筆者將在第5章中展開。
1.2.3 剖析spark-shell
通過word count在spark-shell中執行的過程,我們想看看spark-shell做了什麼?spark-shell中有以下一段指令碼,見程式碼清單1-1。
程式碼清單1-1 spark-shell
function main() { if $cygwin; then stty -icanonmin 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 "${SUBMISSION_OPTS[@]}" spark-shell "${APPLICATION_OPTS[@]}" sttyicanon echo > /dev/null 2>&1 else export SPARK_SUBMIT_OPTS "$FWDIR"/bin/spark-submit --class org.apache.spark.repl.Main "${SUBMISSION_OPTS[@]}" spark-shell "${APPLICATION_OPTS[@]}" fi }
我們看到指令碼spark-shell裡執行了spark-submit指令碼,那麼開啟spark-submit指令碼,發現其中包含以下指令碼。
exec "$SPARK_HOME"/bin/spark-class org.apache.spark.deploy.SparkSubmit "${ORIG_ARGS[@]}"
指令碼spark-submit在執行spark-class指令碼時,給它增加了引數SparkSubmit 。開啟spark-class指令碼,其中包含以下指令碼,見程式碼清單1-2。
程式碼清單1-2 spark-class
if [ -n "${JAVA_HOME}" ]; then RUNNER="${JAVA_HOME}/bin/java" else if [ `command -v java` ]; then RUNNER="java" else echo "JAVA_HOME is not set" >&2 exit 1 fi fi exec "$RUNNER" -cp "$CLASSPATH" $JAVA_OPTS "[email protected]"
讀到這,應該知道Spark啟動了以SparkSubmit為主類的jvm程序。
為便於在本地能夠對Spark程序使用遠端監控,給spark-class指令碼增加追加以下jmx配置:
JAVA_OPTS="-XX:MaxPermSize=128m $OUR_JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=10207 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"
在本地開啟jvisualvm,新增遠端主機,如圖1-11所示:
圖1-11 新增遠端主機
右鍵單擊已新增的遠端主機,新增JMX連線,如圖1-12:
圖1-12新增JMX連線
選擇右側的“執行緒”選項卡,選擇main執行緒,然後點選“執行緒Dump”按鈕,如圖1-13。
圖1-13檢視Spark執行緒
從dump的內容中找到執行緒main的資訊如程式碼清單1-3所示。
程式碼清單1-3 main執行緒dump資訊
"main" - Thread [email protected] java.lang.Thread.State: RUNNABLE at java.io.FileInputStream.read0(Native Method) at java.io.FileInputStream.read(FileInputStream.java:210) at scala.tools.jline.TerminalSupport.readCharacter(TerminalSupport.java:152) at scala.tools.jline.UnixTerminal.readVirtualKey(UnixTerminal.java:125) at scala.tools.jline.console.ConsoleReader.readVirtualKey(ConsoleReader.java:933) at scala.tools.jline.console.ConsoleReader.readBinding(ConsoleReader.java:1136) at scala.tools.jline.console.ConsoleReader.readLine(ConsoleReader.java:1218) at scala.tools.jline.console.ConsoleReader.readLine(ConsoleReader.java:1170) at org.apache.spark.repl.SparkJLineReader.readOneLine(SparkJLineReader.scala:80) at scala.tools.nsc.interpreter.InteractiveReader$class.readLine(InteractiveReader.scala:43) at org.apache.spark.repl.SparkJLineReader.readLine(SparkJLineReader.scala:25) at org.apache.spark.repl.SparkILoop.readOneLine$1(SparkILoop.scala:619) at org.apache.spark.repl.SparkILoop.innerLoop$1(SparkILoop.scala:636) at org.apache.spark.repl.SparkILoop.loop(SparkILoop.scala:641) at org.apache.spark.repl.SparkILoop$$anonfun$process$1.apply$mcZ$sp(SparkILoop.scala:968) at org.apache.spark.repl.SparkILoop$$anonfun$process$1.apply(SparkILoop.scala:916) at org.apache.spark.repl.SparkILoop$$anonfun$process$1.apply(SparkILoop.scala:916) at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135) at org.apache.spark.repl.SparkILoop.process(SparkILoop.scala:916) at org.apache.spark.repl.SparkILoop.process(SparkILoop.scala:1011) at org.apache.spark.repl.Main$.main(Main.scala:31) at org.apache.spark.repl.Main.main(Main.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.spark.deploy.SparkSubmit$.launch(SparkSubmit.scala:358) at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:75) at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
從main執行緒的棧資訊中看出程式的呼叫順序:SparkSubmit.main→repl.Main→SparkILoop.process。SparkILoop.process方法中會呼叫initializeSpark方法,initializeSpark的實現見程式碼清單1-4。
程式碼清單1-4 initializeSpark的實現
def initializeSpark() { intp.beQuietDuring { command(""" @transient val sc = { val _sc = org.apache.spark.repl.Main.interp.createSparkContext() println("Spark context available as sc.") _sc } """) command("import org.apache.spark.SparkContext._") } }
我們看到initializeSpark呼叫了createSparkContext方法,createSparkContext的實現,見程式碼清單1-5。
程式碼清單1-5 createSparkContext的實現
def createSparkContext(): SparkContext = { val execUri = System.getenv("SPARK_EXECUTOR_URI") val jars = SparkILoop.getAddedJars val conf = new SparkConf() .setMaster(getMaster()) .setAppName("Spark shell") .setJars(jars) .set("spark.repl.class.uri", intp.classServer.uri) if (execUri != null) { conf.set("spark.executor.uri", execUri) } sparkContext = new SparkContext(conf) logInfo("Created spark context..") sparkContext }
這裡最終使用SparkConf和SparkContext來完成初始化,具體內容將在“第3章SparkContext的初始化”講解。程式碼分析中涉及的repl主要用於與Spark實時互動。
1.3 閱讀環境準備
準備Spark閱讀環境,同樣需要一臺好機器。筆者除錯原始碼的機器的記憶體是8GB。原始碼閱讀的前提是首先在IDE環境中打包、編譯通過。常用的IDE有 IntelliJ IDEA、Eclipse,筆者選擇用Eclipse編譯Spark,原因有二:一是由於使用多年對它比較熟悉,二是社群中使用Eclipse編譯Spark的資料太少,在這裡可以做個補充。筆者在windows系統編譯Spark原始碼,除了安裝JDK外,還需要安裝以下工具。
(1)安裝Scala
由於Spark 1.20版本的sbt裡指定的Scala版本是2.10.4,具體見Spark原始碼目錄下的檔案\project\plugins.sbt中,有一行:scalaVersion := "2.10.4"。所以選擇下載scala-2.10.4.msi,下載地址:http://www.scala-lang.org/download/
下載完畢,安裝scala-2.10.4.msi。
(2)安裝SBT
由於Scala使用SBT作為構建工具,所以需要下載SBT。下載地址: http://www.scala-sbt.org/,下載最新的安裝包sbt-0.13.8.msi並安裝。
(3)安裝Git Bash
由於Spark原始碼使用Git作為版本控制工具,所以需要下載Git的客戶端工具,筆者推薦使用Git Bash,因為它更符合Linux下的操作習慣。下載地址:http://msysgit.github.io/,下載最新的版本並安裝。
(4)安裝Eclipse Scala IDE外掛
Eclipse通過強大的外掛方式支援各種IDE工具的整合,要在Eclipse中編譯、除錯、執行Scala程式,就需要安裝Eclipse Scala IDE外掛。下載地址:http://scala-ide.org/download/current.html。
圖1-14 Eclipse Scala IDE外掛安裝地址
在Eclipse中選擇“Help”選單,然後選擇“Install New Software…”選項,開啟Install對話方塊,如圖1-15所示:
圖1-15 安裝Scala IDE外掛
點選“Add…”按鈕,開啟“Add Repository”對話方塊,輸入外掛地址,如1-16圖所示:
圖1-16 新增Scala IDE外掛地址
全選外掛的內容,完成安裝,如圖1-17所示:
圖1-17 安裝Scala IDE外掛
1.4 Spark原始碼編譯與除錯
1.下載Spark原始碼
首先,訪問Spark官網http://spark.apache.org/,如圖1-18所示:
圖1-18Spark官網
點選“Download Spark”按鈕,在下一個頁面找到git地址,如圖1-19所示:
圖1-19 Spark官方git地址
開啟Git Bash工具,輸入git clone git://github.com/apache/spark.git命令將原始碼下載到本地,如1-20圖所示:
圖1-20下載Spark原始碼
2.構建Scala應用
使用cmd命令列進到Spark根目錄,執行sbt命令。會下載和解析很多jar包,要等很長的時間,筆者大概花費了一個多小時,才執行完。
3.使用sbt生成eclipse工程檔案
等sbt提升符>出現後,輸入eclipse命令,開始生成eclipse工程檔案,也需要花費很長的時間,筆者本地大致花費了40分鐘。完成時的狀況,如圖1-21所示:
圖1-21 sbt編譯過程
現在我們檢視Spark下的子資料夾,發現其中都生成了.project和.classpath檔案。比如mllib專案下就生成了.project和.classpath檔案,如圖1-22所示:
圖1-22sbt生成的專案檔案
4.編譯Spark原始碼
由於Spark使用Maven作為專案管理工具,所以需要將Spark專案作為Maven專案匯入到Eclipse中,如1-23圖所示:
圖1-23 匯入Maven專案
點選Next按鈕進入下一個對話方塊,如圖1-24所示:
圖1-24 選擇Maven專案
全選所有專案,點選finish按鈕。這樣就完成了匯入,如圖1-25所示:
圖1-25 匯入完成的專案
匯入完成後,需要設定每個子專案的build path。右鍵單擊每個專案,選擇“Build Path”→“Configure Build Path…”,開啟Build Path對話方塊,如圖1-26:
圖1-26 Java編譯目錄
點選“Add External JARs…”按鈕,將Spark專案下的lib_managed資料夾的子資料夾bundles和jars內的jar包新增進來。
注意:lib_managed/jars資料夾下有很多打好的spark的包,比如:spark-catalyst_2.10-1.3.2-SNAPSHOT.jar。這些jar包有可能與你下載的Spark原始碼的版本不一致,導致你在除錯原始碼時,發生jar包衝突。所以請將它們排除出去。
Eclipse在對專案編譯時,筆者本地出現了很多錯誤,有關這些錯誤的解決見附錄H。所有錯誤解決後執行mvn clean install,如圖1-27所示:
圖1-27 編譯成功
5.除錯Spark原始碼
以Spark原始碼自帶的JavaWordCount為例,介紹如何除錯Spark原始碼。右鍵單擊JavaWordCount.java,選擇“Debug As”→“Java Application”即可。如果想修改配置引數,右鍵單擊JavaWordCount.java,選擇“Debug As”→“Debug Configurations…”,從開啟的對話方塊中選擇JavaWordCount,在右側標籤可以修改Java執行引數、JRE、classpath、環境變數等配置,如圖1-28所示:
圖1-28原始碼除錯
讀者也可以在Spark原始碼中設定斷點,進行跟蹤除錯。
1.5 小結
本章通過引導大家在Linux作業系統下搭建基本的執行環境,並且介紹spark-shell等指令碼的執行,目的無法是為了幫助讀者由淺入深的進行Spark原始碼的學習。由於目前多數開發工作都在Windows系統下,並且Eclipse有最廣大的使用者群,即便是一些開始使用IntelliJ的使用者對Eclipse也不陌生,所以在Windows環境下搭建原始碼閱讀環境時,選擇這些最常用的工具,希望能降低讀者的學習門檻,並且替大家節省時間。
相關推薦
《深入理解Spark:核心思想與原始碼分析》(第2章)
《深入理解Spark:核心思想與原始碼分析》一書第一章的內容請看連結《第1章 環境準備》 本文主要展示本書的第2章內容: Spark設計理念與基本架構 “若夫乘天地之正,而御六氣之辯,以遊無窮者,彼且惡乎待哉?” ——《莊子·逍遙遊》 n本章導讀: 上一章,介紹了Spark環境的搭建,為方便讀
《深入理解SPARK:核心思想與原始碼分析》一書正式出版上市
自己犧牲了7個月的週末和下班空閒時間,通過研究Spark原始碼和原理,總結整理的《深入理解Spark:核心思想與原始碼分析》一書現在已經正式出版上市,目前京東、噹噹、天貓等網站均有銷售,歡迎感興趣的同學購買。我開始研究原始碼時的Spark版本是1.2.0,經過7個多月的研
《深入理解Spark:核心思想與原始碼分析》(前言及第1章)
自己犧牲了7個月的週末和下班空閒時間,通過研究Spark原始碼和原理,總結整理的《深入理解Spark:核心思想與原始碼分析》一書現在已經正式出版上市,目前亞馬遜、京東、噹噹、天貓等網站均有銷售,歡迎感興趣的同學購買。我開始研究原始碼時的Spark版本是1.2.0,經過7個多月的研究和出版社近4個月的流
《深入理解SPARK:核心思想與原始碼分析》——SparkContext的初始化(仲篇)——SparkUI、環境變數及排程
《深入理解Spark:核心思想與原始碼分析》一書第一章的內容請看連結《第1章 環境準備》 《深入理解Spark:核心思想與原始碼分析》一書第二章的內容請看連結《第2章 SPARK設計理念與基本架構》 由於本書的第3章內容較多,所以打算分別開闢四篇隨筆分別展現。 本文展現第3章第二部分的內容:
《深入理解Spark:核心思想與原始碼分析》——SparkContext的初始化(伯篇)——執行環境與元資料清理器
《深入理解Spark:核心思想與原始碼分析》一書第一章的內容請看連結《第1章 環境準備》 《深入理解Spark:核心思想與原始碼分析》一書第二章的內容請看連結《第2章 SPARK設計理念與基本架構》 由於本書的第3章內容較多,所以打算分別開闢四篇隨筆分別展現。本文展現第3章第一部分的內容: 第3章
《深入理解Spark-核心思想與原始碼分析》讀書筆記(1)
前兩章 第一章主要是講如何安裝和配置spark,以及如何匯入spark原始碼除錯執行;第二章主要講的是上次那本書《Spark快速大資料分析》的內容,科普一下spark的知識。 第三章 SparkContext的初始化 1. 概述 這章的主要內容就
深入理解Nginx:模組開發與架構解析
讀書筆記 第一部分 Nginx能幫我們做什麼 第1章 研究Nginx前的準備工作 1.1Nginx是什麼 1.2
理解機器學習和深度學習的核心思想與實現思路 (入門與總結)[圖文 + 詳細思路]
本文講解涉及到的核心思想: 機器學習與深度學習: 1:線性迴歸問題。 2:優化搜尋時,步長選取的重要性。 3:為什麼神經網路可以擬合任意的曲線函式。 4:影象識別網路中,為什麼淺層網路只能識別出一些簡單的線,面,隨著網路的加深可以識別出十分複雜的圖案。 1:線性迴歸
《圖解Spark:核心技術與案例實戰》介紹及書附資源
本書中所使用到的測試資料、程式碼和安裝包放在百度盤提供 下載 ,連結: https://pan.baidu.com/s/1sXuOC3J-aHEc0E_kVWLqFg#list/path=%2F 另外在百度盤提供本書附錄 下載 ,連結: https://pan.baidu.com/s/1sO8NXqry
深入理解Nginx:模組開發與架構解析 讀書筆記
Nginx的作用 當我們在設計高效能web伺服器的時候,我們第一選擇是使用Nginx,因為nginx對伺服器效能上的挖掘已經到了非常高的水平,Nginx採用了無阻塞分階段的事件驅動框架。當nginx不能那個完全實現我們的業務需求的時候,我們可以在Nginx後端搭建一個非ng
《大型網站技術架構:核心原理與案例分析》-- 讀書筆記 (5) :網購秒殺系統
案例 並發 刷新 隨機 url 對策 -- 技術 動態生成 1. 秒殺活動的技術挑戰及應對策略 1.1 對現有網站業務造成沖擊 秒殺活動具有時間短,並發訪問量大的特點,必然會對現有業務造成沖擊。對策:秒殺系統獨立部署 1.2 高並發下的應用、
《大型網站技術架構:核心原理與案例分析》【PDF】下載
優化 均衡 1.7 3.3 架設 框架 應用服務器 博客 分布式服務框架 《大型網站技術架構:核心原理與案例分析》【PDF】下載鏈接: https://u253469.pipipan.com/fs/253469-230062557 內容簡介 本書通過梳理大型網站技
閱讀《大型網站技術架構:核心原理與案例分析》第五、六、七章,結合《河北省重大技術需求征集系統》,列舉實例分析采用的可用性和可修改性戰術
定時 並不會 表現 做出 span class 硬件 進行 情況 網站的可用性描述網站可有效訪問的特性,網站的頁面能完整呈現在用戶面前,需要經過很多個環節,任何一個環節出了問題,都可能導致網站頁面不可訪問。可用性指標是網站架構設計的重要指標,對外是服務承諾,對內是考核指
《大型網站技術架構:核心原理與案例分析》結合需求征集系統分析
運行 模塊 正常 一致性hash 產品 進行 OS 很多 層次 閱讀《大型網站技術架構:核心原理與案例分析》第五、六、七章,結合《河北省重大技術需求征集系統》,列舉實例分析采用的可用性和可修改性戰術,將上述內容撰寫成一篇1500字左右的博客闡述你的觀點。 閱
《大型網站技術架構:核心原理與案例分析》讀後感
TP bubuko 一個 nbsp 分享 架構 優化 技術分享 src 李智慧的著作《大型網站技術架構:核心原理與案例分析》,寫得非常好, 本著學習的態度,對於書中的關於性能優化的講解做了一個思維導圖,供大家梳理思路和學習之用。拋磚引玉。 《大型網站技術架構
老生常談:Promise 用法與原始碼分析
此文章是幾個月前寫得,發現沒有發表過,就在此發表一下。 背景 Promise本身是一個非同步程式設計的方案,讓處理過程變得更簡單。es6引入promise特性來處理JavaScript中的非同步場景。以前,處理非同步最常用的方法就是回撥函式,但是當過程稍微複雜一點,多個非同步操作集中在一起的時候
《大型網站技術架構:核心原理與案例分析》筆記
· 大型網站軟體系統的特點 · 大型網站架構演化發展歷程 · 初始階段的網站架構 · 需求/解決問題 · 架構 · 應用服務和資料
深入理解vue中的slot與slot-scope (簡單易懂)
走在前端的大道上 插槽,也就是slot,是元件的一塊HTML模板,這塊模板顯示不顯示、以及怎樣顯示由父元件來決定。 實際上,一個slot最核心的兩個問題在這裡就點出來了,是顯示不顯示和怎樣顯示。 由於插槽是一塊模板,所以,對於任何一個元件,從模板種類的角度來分,其實都可以
課時17 第三課Spark內部原理剖析與原始碼閱讀(五)
為何spark shuffle比mapreduce shuffle慢? 主要是spark shuffle的shuffle read階段還不夠優秀,它是基於hashmap實現的,shuffle read會把shuffel write階段已經排序資料給重新轉成亂序的,轉成亂序之後又做了排序,導致非常低效,sp
《大型網站技術架構:核心原理與案例分析李智慧》pdf附網盤下載連結送給還在迷茫的你
Detect languageAfrikaansAlbanianAmharicArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chines