1. 程式人生 > >《深入理解Spark:核心思想與原始碼分析》(前言及第1章)

《深入理解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本身帶有除錯的功能,每當你閱讀原始碼,陷入重圍時,除錯能讓我們更加理解執行期的系統。如果沒有除錯功能,不敢想象閱讀原始碼的困難。

本章的主要目的是幫助讀者構建原始碼學習環境,主要包括以下內容:

  1. 在windows環境下搭建原始碼閱讀環境;
  2. 在Linux搭建基本的執行環境;
  3. 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中的slotslot-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