分享

想研读下spark的源码,怎么搭阅读和调试的环境呢?

本帖最后由 PeersLee 于 2017-8-16 15:24 编辑
问题导读:

1. 如何选择ide?
2. 如何Build Spark?
3. 如何工程导入?
4. SBT 如何配置?
5. 如何调试?




解决方案:

这个问题被很多人问过,很早就想写一下。尤其是如何在 IntelliJ IDEA 中单步调试 Spark。若无特殊说明,本篇均以撰稿时最新的 Spark 2.0 SNAPSHOT 和 IntelliJ IDEA 2016 为基础,并以 SBT 为主要 build 工具。


IDE 选择

Spark 的主力 IDE 无疑是 IntelliJ IDEA。在 Databricks 我也见过直接用 Vim、Sublime 的同事,然而但凡用 IDE 的,清一色是 IDEA,从没见过谁用 Eclipse 和/或 NetBeans。所以,作为主力 contributor 的日常 IDE,IDEA 一定是最驯顺的。(就个人体验而言,IDEA 也是我用过的最好的 Java/Scala IDE。)
有一点需要提前说明的是,不要指望让 IDEA 全权搞定工程导入、build、test、debug 的全部环节。出于历史原因,Spark 采用了 Maven 和 SBT 两套 build 系统,二者互相交织,再加上引入了 assembly jar,使得整个 build 系统变得对 IDE 不那么友好。截至撰稿为止,我尚未见过任何一套可以在单个 IDE 内搞定全套流程的方法。不过不用紧张,debugger 还是可以用的。

Build Spark

在将 Spark 工程导入 IDEA 之前,最好先 build 一遍 Spark,至少完成编译步骤。这是因为编译过程中还会自动生成一些源码。尤其是 Spark 2.0 中 SQL parser 改用 ANTLR 实现。如果不经编译直接将工程导入 IDEA,parser 相关的 class 会出现引用缺失。
Build Spark 的详细步骤参见官网文档。这里只提一些额外的注意事项。
首先,请努力建设有中国特色的社会主义个人网络访问渠道。(听说朝廷要大力发展大数据来着?呵呵。)其次,和一般理解不同,build Spark 其实不需要单独安装 Scala 和 SBT。Spark 源码中的 build/sbt 脚本会自动下载指定版本的 SBT,而 SBT 在 build Spark 的过程中又会自动下载指定版本的 Scala。所以除非你需要脱离 Spark 单独使用 Scala,否则无须另行安装。对于 Maven,build/mvn 脚本的行为也类似。
最后就是 profile “套餐”的选择。这部分内容官网文档中已经有所涉及。详细的 profile 定义请参见 Spark 根目录下的 pom.xml。此外,目前 Spark 同时支持 Scala 2.10 和 2.11,其中 Spark 2.0 默认启用 2.11。查看 pom.xml 的时候会看到 scala-2.10 和 scala-2.11 这两个 profile。但用 SBT build 时,启用这两个 profile 需要用 -D 而不是 -P,如:
[mw_shl_code=scala,true]build/sbt -Dscala-2.10 -Phive clean assembly/assembly[/mw_shl_code]
简单说,这是因为 Spark 的 SBT build 对 Scala 版本的设置做了特殊处理,标准的 Maven -P 参数是无效的。注意:正在开发中的 Spark 2.0 已经取消了 assembly jar,把上述的 assembly/assembly 替换为 package 即可。


工程导入

新近版本的 IDEA 对 SBT 的支持已经改进了很多,早就不再需要 sbt-idea 插件。此外,由于 Spark 同时使用 Maven 和 SBT 两套 build 系统,用 Maven 和 SBT 都可以顺利导入。社区里,不同的开发者对 SBT 和 Maven 的偏好各有不同。我印象里 Cloudera 的人相对来说更喜欢 Maven,因为 Maven 对 release publishing 更友好,更方便他们将 Spark 集成进 CDH。而 Databricks 内一般用 SBT 的更多,主要是因为 SBT REPL 开发体验更流畅。
我个人的偏好比较分裂——工程导入用 Maven,build 和 test 用 SBT。选择依据主要是最大化日常开发的迭代速度。
IDEA 在导入 SBT 工程的时候会出现全局卡死的情况。整个导入过程是同步的,完成之前无法执行任何操作。偏偏 SBT 的依赖解析又极慢,再配合中国特色的社会主义和谐网络,每回导入打个坐,一年下来不是升仙就是成佛了吧……用 Maven 导入 IDEA 工程,这个问题就缓解了许多。Maven 的依赖解析更快,而且 IDEA 的 Maven 支持更成熟,整个解析过程是异步的,不影响其他操作。导入方法也极简单:File / Open,选定 Spark 根目录下的 pom.xml,确定即可。


2017-08-16_151009.jpg

用 Maven 导入工程的另一个优点是,在 IDEA 的 Maven tool window(View > Tool Windows > Maven Projects)里可以很方便地调整 active profiles。假设当前 branch 开发的功能仅和 Hadoop 2.2 下的 Spark SQL 的 Hive 集成相关,那么就可以打开 hadoop-2.2 和 hive profile,关闭其他的 profile。这样一来,无关的 sub-project 就不会被激活,代码索引、依赖解析更快,内存占用也更低。

SBT 配置

Spark SBT build 中包含多个 sub-project,日常开发调试时经常需要切换到不同的 sub-project。因此我会简单调整一下 SBT 的 prompt string,以便显示当前的 project 名称。这步并非必须。在 $HOME/.sbt/0.13/global.sbt 中添加以下内容即可:import scala.Console.{BLUE, RESET, UNDERLINED}

[mw_shl_code=scala,true]shellPrompt := { state =>
  val projectId = Project.extract(state).currentProject.id
  s"$BLUE${UNDERLINED}sbt ($projectId)>$RESET "
}[/mw_shl_code]

效果如下:
[mw_shl_code=scala,true]$ ./build/sbt -Phive -Phive-thriftserver
...
sbt (spark)> project hive
...
sbt (hive)>[/mw_shl_code]

调试

一个困扰着很多初学者,甚至是一些已经有相当 Spark 开发经验的工程师的问题,就是如何在 IDEA 中调试 Spark(注意这里指的是 Spark 本身,而不是基于 Spark 开发的应用)。可能是由于 SBT / Maven 混用以及使用 assembly jar 的缘故,在 IDEA 里直接 build 和调试 Spark 并不方便,往往会碰到一些奇怪的错误,以至于 IDEA 完全退化成一个代码阅读工具和编辑器。这个问题实际上可以通过远程调试很好地解决。以下以监听模式(listen mode)为例演示如何在 IDEA 内“远程”调试本地 SBT 内启动的 Spark test case。
在 IDEA 中建立 Remote Debugging Configuration
选取菜单项 Run > Edit Configurations... 点击左上角加号,选取 Remote 建立一套远程调试配置,并命名为“Remote Debugging (listen)”:

2017-08-16_151209.jpg

2017-08-16_151324.jpg

2017-08-16_151334.jpg

[mw_shl_code=scala,true]sbt (hive)> set javaOptions in Test += "-agentlib:jdwp=transport=dt_socket,server=n,suspend=n,address=localhost:5005"[/mw_shl_code]

(依具体情况,server、suspend、address 三个参数可以按需调整。各参数含义、取值参见 Oracle官方文档。)

2017-08-16_151614.jpg

其他

sparkShell task

Spark SBT build 中定义了一个 SBT task sparkShell,可以直接在 SBT 内启动一个 Spark shell。做简单测试时很方便。


作者:连城
链接:https://www.zhihu.com/question/24869894/answer/97339151
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


本帖被以下淘专辑推荐:

已有(1)人评论

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条