1.Spark项目的创建
说明一点,这里创建的项目,比之前稍微复杂一点点--基于maven的聚合和继承项目。
- 创建父模块
- 指定maven坐标
- 执行项目的存储位置
- 注意:父模块,一般不做开发,也就可以删除src相关目录;主要的作用就是用来管理所有的子模块,管理整个项目中使用到的依赖及其版本。删除src目录
- maven依赖,先不管理。
- 创建子目录--通用common右键项目名称,创建Module
- 跳过,不用选择archetype骨架
- 指定子模块的坐标
- 指定子模块的存储位置
- 此时查看项目父模块的pom文件,多了一个module
- 创建子模块--sparkcore右键项目名称,创建Module
- 跳过,不用选择archetype骨架
- 指定子模块的坐标
- 指定子模块存储位置
- 同理在parent的pom中自然又会多出一个module
- 指定项目的依赖在木模块中添加依赖
- 查看子模块的变化
- 好处是,子模块里面就可以拥有父模块所有的依赖,坏处是强迫所有的子模块继承所有依赖。所以我们在生产环境中要做到有选择性的继承。所以就需要将父模块的依赖管理(有个标签dependencyManagement)起来,不能随随便便的让子模块就都继承。
- 如上图是还没有重新导入依赖。现在开始导入依赖:
- 子模块之前的依赖消失了:
- 自然之前编写的相关逻辑就会报错,因为找不到依赖了:
- 有选择的继承依赖
- 处理spark的依赖
- 父模块完整的pom依赖
- common的pom文件
- core的pom文件
2. 项目编码
2.1. 添加模块为scala项目
第一步,在src下面创建一个scala目录,用于编写scala代码,并且将scala的目录指定为source root
发现无法直接创建scala的class,已经拥有了scala的依赖,
修改project structure,添加scala模块到core中
删除并重新添加
2.2. 项目具体的代码
需要注意的是,入口类为SparkContext。
不同版本有不同的SparkContext,java版本的是JavaSparkContext,scala的版本就是SparkContext;SparkSQL的入口有SQLContext、HiveContext;SparkStreaming的入口又是StreamingContext。
- java版本
- java-lambda版本
这里需要注意一个问题,将java的sdk的版本提高到至少1.8.在pom中加入如下的内容即可:
- scala版本--基础版本
- scala--标准版
2.3. Master URL
首先在编程过程中,至少需要给spark程序传递一个参数master-url,通过sparkConf.setMaster来完成。改参数,代表的是spark作业的执行方式,或者指定的spark程序的cluster-manager的类型。
3 spark日志的管理
- 全局管理 就是项目classpath下面引入log4j.properties配置文件进行管理
- 局部管理 就是在当前类中进行日志的管理。
4. spark程序的其它提交方式
4.1. 加载hdfs中的文件
出现如下问题:
java.lang.IllegalArgumentException: java.net.UnknownHostException: ns1
解决方案,最简单的就是将hadoop的两个配置文件core-site.xml和hdfs-site.xml添加到项目的classpath中即可。
但是此时在此基础之上,将textFile去加载本地的文件
则会报错:
java.lang.IllegalArgumentException: Pathname /E:/data/hello.txt from hdfs://ns1/E:/data/hello.txt is not a valid DFS filename
原因就在于,已经在classpath下面加载了hdfs-site.xml和core-site.xml的配置文件,则会自动理解输入的文件路径为hdfs的,自然会报错。所以,在此情况下还想加载本地文件,那么就告诉机器以本地文件的格式或者协议读取即可
4.2提交spark程序到集群中
- 程序打包 --->基于命令行的打包方式
- maven的声明周期 maven的声明周期主要有3大声明周期: Clean ---->清理项目根目录下面的target中的数据 clean Default compile --->编译,把.java/.scala编译成.class test --->测试,执行src/test/java|scala目录中的单元测试 package ——->打包,把这一堆.class和配置文件打包成一个.jar包 install --->安装,把package生成的.jar安装到maven的本地仓库,只能当前机器可以依赖 deploy --->部署,把install安装的.jar发布到maven的私服或者中央仓库中,这样互联网上的程序员都可以依赖的 Site site --->站点,编码完成之后,生成本项目中的站点信息,比如开发者都有谁,项目简介是什么,公司简介,公司url地址等等。 上述生命周期中的构建命令,执行顺序依次为:clean compile test package install deploy 执行特点:一步构建,执行顺序后面的命令,会自动执行前面的构建操作。
- 不需要第三方依赖 直接在项目的根目录下面执行如下命令:
mvn package -DskipTests
- 需要第三方依赖 此时就需要在pom中添加一个第三方的插件来完成打包
执行命令:
mvn clean package -DskipTests
一个思考的问题:服务器已经有了spark的依赖包,在上述的打包过程中又把spark的依赖包打了一遍,多余,还有可能因为版本不一致,造成版本冲突?
通常的解决方式,不要将集群中已经存在的依赖打进去。
scope表示当前的依赖的作用域,常见有4个取值范围: compiled : 默认的取值范围,当前的依赖在源码期,编译器,运行期都有效 test : 只在src/test/*下面有效 provided : 表示当前依赖已经被提供了,所以只在源码编写期,编译器有效,运行期不起作用 runtime : 表示当前依赖只在运行期使用,在源码,编译器无效,mysql驱动包
上述打包方式太啰嗦,如果不需要第三方依赖的打包的话,直接使用idea打包:
进入project structure
选择artifacts创建jar
起jar名称,选择打包的依赖
选择build artifacts
选择build对应的artifact
会在项目的根目录下面生成一个out目录,在该目录中就存放这build的artifact,文件夹名称就是前面起的名字
打包完成
- 提交standalone在追踪spark-shell提交程序的代码过程中,发现执行了如下一句话:
- 所以,spark程序提交到集群,就应该是通过spark-submit脚本来完成的。 spark-submi-wc-local脚本
一个疑惑的问题,在local的方式中,可以看到foreach的结果,但是client模式下面就看不到这个结果,这是为何?
算子操作都是在worker中执行的,包括foreach操作,所以要想看结果就应该去worker上面查看,而不是提交作业的本机。
- 提交yarn集群 spark基于yarn集群的运行方式,是在国内最常见的一种方式。
- client
- cluster
注意:
1.需要将jar的路径修改到一个各个节点能够共享的位置,因为在cluster模式下面,driver不一定在提交jar的所在机器启动,比如:
现在在bigdata02上面是不可能找在01上面的jar的,所以需要将jar进行共享。
2.大家直接基于yarn模式进行运行,肯定会报错,一般报的错误就是虚拟内存超过的物理内存这个错误。
Container killed by YARN for exceeding memory limits. 15.6 GB of 15.5 GB physical memory used.
解决问题:
在yarn-site.xml中添加如下两个配置