文档说明
1.1、文档描述
本文档以笔记的形式整理记录此次阅读spark2.4.4源码的理解与过程,希望做到尽可能的详细记录下spark2.4.4源码中的一些关键细节。作为日后工作解决工作中遇到的问题的参考。
本次的阅读无任何需求背景,旨在复习和学习一下spark2.4,源码阅读分为两个部分,第一部分是spark应用程序完整的执行周期,尽量仔细的过一遍运行机制;第二部分是spark 架构各个核心模块研读。关于spark的各个功能模块,根绝源码理解的程度来进行
1.2、阅读对象
主要是本人自己,如果对spark有兴趣的同学,也可以阅读。同时欢迎指正和参与
阅读环境介绍
OS 版本:win10 1903 企业版
JDK 版本:jdk1.8.0_181
IEDA 版本: 2019.2.4
Maven 版本: 3.5.4
Spark 源码版本:2.4.4
源码导入过程
1、在官网上下载好源码包spark-2.4.4.tgz,然后解压到自己的工程目录下,如下:
2、启动idea后,依次点击File à Open 然后弹出如下对话框,找到你源码保存的位置,先选中源码目录,然后点击ok,此时源码即将开始导入,但是此时会使用idea 内置的maven进行项目的导入,虽然也可以用,但是我还是选择了自己安装好的maven环境。
3、将maven改为我们自己安装的maven
依次点击File à Settings à Build, Execution, Deployment à Build Tools à Maven
在此页面将Maven home directory 对应的路径改为自己maven的安装路径,点击OK即可。
设置完成后就等待着idea,下载和索引好所有的依赖吧
所有依赖处理好了以后,如下面所示,左边的项目模块和右边的maven模块上没有一条红色的波浪线。
源码阅读第一部分
从一个 org.apache.spark.examples.JavaWordCount提交开始.
最简单提交指令
Spark-submit \
--class org.apache.spark.examples.JavaWordCount \
--master yarn \
--deploy-mode client \
/file/path/to/examples.jar /file-path
打开源码bin目录下的spark-submit
我们可以看到,这个shell脚本会执行下面这个类
我们跟着类路径,找到这个类,并且找到入口main函数
我们可以看到,首先是创建了一个SparkSubmit对象,并且override了 parseArguments()方法和doSubmit()方法。然后执行了doSubmit方法,该方法直接调用了super.doSubmit方法。我们跟进去接着看。
这个方法主要执行了parseArgument() 方法,也就是下面的这个方法。这个方法会创建一个SparkSubmitArguments对象。同时也是创建org.apache.spark.launcher.SparkSubmitOptionParse这个对象。这里做一个标记,代码到这里执行到了第81行,我们要跳到SparkSubmitArguments类和SparkSubmitOptionParse这个类中,SparkSubmitArguments继承了SparkSubmitOptionParse,并且完成了参数的识别和封装。
SparkSubmitArguments 这个对象会将我们上面在shell中提交的脚本中的参数进行识别和封装。依次是识别参数,然后合并spark的默认参数,然后忽略设置的参数,然后加载系统环境变量参数,最后校验参数的合法性
当参数parse 和 encapsulated 以后,回到SparkSubmit中的81行,接着换判断是否打印参数,默认是不打印,可以在spark-submit的的时候指定为true。可以用于调试模式。
再接着就是匹配参数中action,如果是submit的话,就执行submit方法。我们这里是提交,所以跟进去看submit方法
submit方法中定义了一个doRunMain,submit方法会判断时候是Stand alone cluster 模式和时候使用rest 方式提交。默认情况下是不会这样执行的。rest 方式是spark内部的提交机制。这点我们先不管,submit方法最主要的是调用了doRunMain方法。也就是上面定义的那个方法了。
在这个方法中,首先会检查参数中是否指定了proxyUser,这个参数是指定spark 程序运行的用户,并且检查了用户是否有提交spark 应用程序的权限。一般在使用了安全管理的集群中配合使用。我们前面的提交脚本中没有指定proxy User,所以这里会直接执行runMain方法。我们跟进去看看runMain 方法
runMain方法首先调用了prepaareSubmitEnvironment()方法,为我们提交的spark程序准备运行环境。我们跟进去看看。我去 500多行代码,不截图了,直接说下干了写什么事吧
1、将我们shell脚本中提交的参数传递给我们写的spark程序,例如yarn、standalone、或、mesos或者k8s上运行
2、将我们提交的程序依赖的包的classpath 准备到一个list中
3、将系统环境变量准备到一个map中
4、将JavaWordCount mian方法准备好
prepaareSubmitEnvironment方法执行完后,接着会使用反射的方式加载我们写的应用程序,然后将其封装成SparkApplication对象。最后调用spark application 对象的start 方法,我们写的程序开始执行了。
到此为止,整个spark submit 执行完毕
现在总结一下,整个过程的核心调用链
Spark-submit 脚本调用à org.apache.spark.deploy.SparkSubmit à {
SparkSubmit调用parseArguments方法进行参数识别,实际上会创建SparkSubmitArguments对象,SparkSubmitArguments实际上是SparkSubmitArguments使用了父类SparkSubmitArgumentsParser的parse方法对参数进行了识别。之后SparkSubmitArguments对象将识别到的参数和集群运行环境进行了合并,之后一起封装成了SparkSubmitArguments对象。
}
接着SparkSubmit调用doSubmit方法,该方法会从SparkSubmitArguments中拿到提交参数,并且调用submit 方法,而submit 方法会去调用runMain方法,该方法最终会将我们提交的程序封装成SparkApplication对象,然后调用start方法,我们的程序开始执行。 |