《深刻理解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核心部分的变化相对仍是不多的,若是对版本不是过于追求,依然能够选择本书。html

 

 

京东:http://item.jd.com/11846120.html java

当当:http://product.dangdang.com/23838168.html linux

亚马逊:http://www.amazon.cn/gp/product/B01A5G5LHK/sr=8-1/qid=1452505597/ref=olp_product_details?ie=UTF8&me=&qid=1452505597&sr=8-1git

 

为了让你们对本书有个大体了解,这里将本书的前言及第一章的内容附上:github

 

前言 

为何写这本书 

         要回答这个问题,须要从我我的的经历提及。说来惭愧,我第一次接触计算机是在高三。当时跟你们一块儿去网吧玩CS,跟身边的同窗学怎么“玩”。正是经过这种“玩”的过程,让我了解到计算机并无那么神秘,它也只是台机器,用起来彷佛并不比打开电视机费劲多少。高考填志愿的时候,凭着直觉“糊里糊涂”就选择了计算机专业。等到真正学习计算机课程的时候却又发现,它其实很难! shell

         早在2004年,还在学校的我跟不少同窗同样,喜欢看Flash,也喜欢谈论Flash甚至作Flash。感受Flash正如它的名字那样“闪光”。那些年,在学校里,知道Flash的人可要比知道Java的人多得多,这说明当时的Flash十分火热。此外Oracle也成为关系型数据库里的领军人物,不少人甚至以为懂Oracle要比懂Flash、Java及其它数据库要厉害得多! 数据库

         2007年,笔者刚刚参加工做不久。那时Struts一、Spring、Hibernate几乎能够称为那些用Java做为开发语言的软件公司的三驾马车。很快随着Struts2的诞生,很快替代了Struts1的地位,让我第一次意识到IT领域的技术更新居然如此之快!随着不少传统软件公司向互联网公司转型,更让人吃惊的是,当初那个敢于技术更新的年轻人Gavin King,也许很难想象他创造的Hibernate也难以确保其地位,iBATIS诞生了! apache

         2010年,有关Hadoop的技术图书涌入中国,当时不少公司用它只是为了数据统计、数据挖掘或者搜索。一开始,人们对于Hadoop的认识和使用可能相对有限。大约2011年的时候,关于云计算的概念在网上吵得火热,当时依然在作互联网开发的我,对其只是“道听途说”。后来跟同事借了一本有关云计算的书,回家挑着看了一些内容,以后什么也没有弄到手,怅然若失!上世纪60年代,美国的军用网络做为互联网的雏形,不少内容已经与云计算中的某些说法相相似。到上世纪80年代,互联网就已经开启了云计算,为何现在又要重提这样的概念?这个问题笔者可能回答不了,仍是交给历史吧。 编程

         2012年,国内又呈现出大数据热的态势。从国家到媒体、教育、IT等几乎全部领域,人人都在谈大数据。个人亲戚朋友中,不管老师、销售仍是工程师们均可以对大数据谈谈本身的见解。我也找来一些Hadoop的书籍进行学习,但愿能在其中探索到大数据的味道。 vim

         有幸在工做过程当中接触到阿里的开放数据处理服务(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的最新源码。 

联系方式 

         本书内容不少,限于笔者水平有限,书中内容不免有错误之处。在本书出版的任什么时候间,若是你对本书有任何问题或者意见均可以经过邮箱beliefer@163.com或者博客http://www.cnblogs.com/jiaan-geng/联系我,给我提交你的建议或者想法,我本人将怀着一颗谦卑之心与你们共同进步。 

致谢 

         感谢苍天,让我生活在这样一个时代接触互联网和大数据;感谢父母,这么多年来,在学习、工做及生活上的帮助与支持;感谢妻子在生活中的照顾和谦让。 

         感谢杨福川编辑和高婧雅编辑给予本书出版的大力支持与帮助。 

         感谢冰夷老大和王贲老大让我有幸加入阿里,接触大数据应用;感谢和仲对Galaxy和Garuda耐心细致的讲解以及对Spark的推荐;感谢张中在百忙之中给本书写评语;感谢周亮、澄苍、民瞻、石申、清无、少侠、征宇、三步、谢衣、晓5、法星、曦轩、九翎、峰阅、丁卯、阿末、紫丞、海炎、涵康、云飏、孟天、零1、六仙、大知、井凡、隆君、太奇、晨炫、既望、宝升、都灵、鬼厉、归钟、梓撤、昊苍、水村、惜冰、惜陌、元乾等同窗在工做上的支持和帮助。

耿嘉安

北京

 

 

第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并安装。

下载地址:

http://www.oracle.com/technetwork/java/javase/downloads/index.html

配置环境:

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

下载地址:http://www.scala-lang.org/download/

选择最新的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

下载地址:http://spark.apache.org/downloads.html

选择最新的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 "$@"

 

读到这,应该知道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 t@1
   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

因为笔者本地的Eclipse版本是Eclipse 4.4 (Luna),因此我选择安装插件http://download.scala-ide.org/sdk/lithium/e44/scala211/stable/site,如图1-14:

 

图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环境下搭建源码阅读环境时,选择这些最经常使用的工具,但愿能下降读者的学习门槛,而且替你们节省时间。

相关文章
相关标签/搜索