Spark源码学习时,我们通常很想知道Spark-submit提交之后,Spark都做了什么,这就需要我们对Spark源码进行单步调试。另外,我们在spark on yarn模式下,尤其是yarn-cluster模式下,我们无法连接driver主机,从而完成程序的跟踪和调试。
我们今天主要探讨Spark源码的下载编译,并在spark on yarn 模式下,如何配置远程调试Attach模式来跟踪Spark源码及Spark程序。
Spark程序在yarn-cluster模式下运行,在A主机上提交Spark程序后,A节点向yarn的ResourceManager申请启动ApplicationMaster,这里ApplicationMaster就是我们常说的driver节点,该节点管理该spark程序的运行,单通常不是提交Spark任务的A节点。ResourceManager内部管理启动ApplicationMaster,但是具体启动哪台主机呢?这是由ResourceManager内部根据一定的算法实现的,所以我们难以知道实际的ApplicationMaster的主机Ip,所以这是yarn-cluster模式下调试的难点。
如果要启用远程调试,有两种做法:一是修改配置文件;二是在启动时设置相关参数。
1,修改配置文件法:(不建议这么做)
在spark-defaults.conf:
spark.driver.extraJavaOptions -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 spark.executor.extraJavaOptions -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
配置说明:
1) spark.driver.extraJavaOptions用来调试driver,spark.executor.extraJavaOptions用来调试executor。如果driver和executor不在同一个节点,端口可以相同;如果在同一个节点,端口必须不同。
2) 如果suspend=y,spark进程在启动时会挂起来,等待ideallij远程连接成功之后在继续启动;如果是n,不用等待ideallij远程连接,就启动,但是会一直监听这个端口,等待ideallij远程连接。
2,设置启动参数法:(推荐使用)
在spark-submit启动时,设置如下参数:
--driver-java-options "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
intellij idea提供两种调试模式:attach和listen
在这种模式下,让debuggee监听端口并等待window连接。
1,登录Spark官方网站:Spark官网
2,点击Download进入下载页
3,选择最新的Spark 2.3版本,选择源码,然后下载。
4,选择适合自己网络的最佳镜像链接下载
源码的编译,一是主要便于我们对源码进行阅读,二是便于我们根据需求对Spark源码进行二次开发。例如,我们有大批量的spark程序并发提交,这时候就不再适用spark-submit进行提交,而是直接通过
SparkSubmit.main()
入口进行提交,但Spark并发提交又是不安全的,所以我们对Spark任务提交相关源码进行了二次开发。
1,源码编译
解压完源码包之后,在源码包根目录下执行如下命令:
./build/mvn -Pyarn -Phadoop-2.6 -Dhadoop.version=2.6.0 -DskipTests package
命令说明:
mvn:执行 spark 源码自带的 mvn 脚本进行编译-Pyarn:编译支持yarn运行的相关包-Phadoop-2.6:编译支持hadoop运行相关包,这里我的hadoop环境为2.6版本-Phadoop.version=2.6.0:编译支持的hdfs版本,这里我的hdfs版本是2.6.0版本-DskipTests:跳过Spark源码测试package:mvn打包命令编译效果如下:
异常解决:
第一次编译遇到如下错误,
然后对编译命令添加 -x 参数查看异常详情发现,应该是jar包plexus-utils依赖缺失或版本不对;
./build/mvn -Pyarn -Phadoop-2.6 -Dhadoop.version=2.6.0 -DskipTests package -x
重新更新本地mvn库中plexus-utils包:(如果觉得手工注册jar包到本地mvn库中太复杂,可以将该mvn依赖扔到本地工程中完成下载)
org.codehaus.plexus plexus-utils 3.1.0
然后重新执行编译命令,经过漫长的等待,终于编译成功。
编译好源码之后,我们就可以将源码导入intellijidea开发工具中。
1,选择 File——》new——》Project from Existing Sources...
2,选择源码根目录
3,选择Import选项,maven,然后next
4,选择将maven工程自动导入,并设置本地mvn库配置
5,选择所有profiles,然后一路next。
经过漫长的等待,终于导入成功。
1,new一个新的scala工程
2,支持maven框架
3,示例代码
package org.stefan.xpj import org.apache.spark.SparkConf import org.apache.spark.sql.SparkSession object DebugMode { def main(args: Array[String]): Unit = { val conf = new SparkConf() conf.setAppName("debug mode") //conf.setMaster("local[2]") conf.setMaster("yarn-cluster") val builder = SparkSession.builder().config(conf) val sparkSession = builder.getOrCreate() val sc = sparkSession.sparkContext val list = List(0,1,2,3,4,5,6,7,8,9) val rdd = sc.parallelize(list) while(true){ rdd.foreach( f=> println(f)) Thread.sleep(30000) } } }
4,pom文件
4.0.0 groupId DebugMode 1.0-SNAPSHOT 2.6.0 2.2.1 0.6.0 2.11.8 2.11 org.apache.spark spark-streaming-kafka-0-10_2.11 2.0.2 org.apache.spark spark-streaming_${scala.binary.version} ${spark.version} org.apache.spark spark-hive_${scala.binary.version} ${spark.version} org.apache.spark spark-sql_${scala.binary.version} ${spark.version} org.apache.maven.plugins maven-surefire-plugin 2.8.1 **/*.java **/*.scala true org.scala-tools maven-scala-plugin 2.15.2 -g:vars true scala-compile-first process-resources compile scala-test-compile process-test-resources testCompile org.apache.maven.plugins maven-compiler-plugin 2.3.2 true org.apache.maven.plugins maven-resources-plugin 3.0.2 false $[*] UTF-8 org.apache.maven.plugins maven-jar-plugin 2.6 true lib/ org.stefan.xpj.DebugMode org.apache.maven.plugins maven-dependency-plugin 2.8 copy-dependencies package copy-dependencies ${project.build.directory}/lib org.apache.maven.plugins maven-shade-plugin 3.0.0 false package shade *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA org.scala-tools maven-scala-plugin ${scala.version}
1,进入Edit Configurations...
2,设置端口以及映射IP
3,将demo打包上传到服务器,并提交任务。
这里我们在spark-submit提交任务时,需要指定参数:
--driver-java-options "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"这里,5005是上面配的端口。
spark-submit完整的提交命令如下:
/opt/software/1/spark-2.2.1-bin-ctcc/bin/spark-submit \ --class com.asiainfo.debug.DebugMode \ --master yarn-cluster \ --num-executors 3 \ --executor-cores 2 \ --executor-memory 1G \ --driver-java-options "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" \ /home/hxxtsx/app/spe_app/jar/DebugMode-1.0-SNAPSHOT.jar
4,查看ApplicationMaster
提交成功后,根据下图URL,我们到yarn的应用程序界面找到我们的程序,并查看ApplicationMaster节点IP。
5,查看Driver节点Ip
此时,我们看到节点名,我们ping一下,得到他的IP:
6,如果本地和Driver节点网络不通,则配置一下跳转映射(如果通则可以省略)
OK,以上准备工作就绪。
7,开始调试