要开始研究spark的源码了,首先要准备好环境,搭建时的考虑如下:
1、开发windows还是首选,所以运行环境限制在windows下
2、既然看源码,集群模式绕不过去,使用spark standalone集群已经能说明绝大部分问题,不采用yarn是因为在windows下面搭建太麻烦了
3、生产环境肯定是集成hive的metastore,这里使用独立的metastore服务方式,hive已经沦落到元数据管理的作用了,当然即便是元数据管理这一项,也是非常重要的,这里使用mysql作为metastore的数据库。
版本上的兼容性是一个大问题,走了一些弯路,最终的版本详情如下:
spark: 3.1.2 with hadoop 2.7,使用的编译好的版本,以下都是使用编译好的版本,能省不少事。spark这个版本决定了hadoop、hive以及scala的版本,其中scala版本的小版本号都需要一致。
hadoop:2.9.2,为了运行在windows上,要从github上找对应版本的wintools。
hive:2.3.9,兼容hadoop 2,但是更重要的适配spark。
scala:2.12.10,这个小版本非常重要,否则在开发时,在IDEA中提交任务到spark standalone集群时,会出现scala版本不一致导致的问题。错误提示没保存,大概就是SerialVersion不一致。出现这个问题的原因是,spark standalone集群使用的自己的scala-library,然后IDEA启动开发的任务时,使用的环境中的scala-library,所以你不光要安装对的版本,也要将它应用的你的开发项目中去。
java:1.8,这个没啥好说的,稳定的一P。
Hive Metastore的搭建
首先,使用单独的metastore作为spark的元数据管理是可行且有必要的,而且我们只需要单独的metastore服务就足够了。但是搭建的过程并不是那么简单。
1、下载的2.3.9没有Windows的命令,从2.1.1里面拷贝过来。
2、hive的配置文件非常关键,这个是初始化mysql数据库和启动metastore的重要配置所在地,而且spark使用hive metastore时同样需要。conf下面的hive-site.xml的参考配置如下:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>hive.metastore.uris</name>
<value>thrift://local.win:9083</value>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>file:///E:/hive/warehouse</value>
<description>unit test data goes in here on your local filesystem</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://local.win:3306/hive?createDatabaseIfNotExist=true&characterEncoding=utf-8&useSSL=false</value>
<description>
JDBC connect string for a JDBC metastore.
To use SSL to encrypt/authenticate the connection, provide database-specific SSL flag in the connection URL.
For example, jdbc:postgresql://myhost/db?ssl=true for postgres database.
</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>Username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
<description>password to use against metastore database</description>
</property>
</configuration>
3、windows下面没有初始化mysql数据库的脚本,需要在linux里面执行,这里需要将hadoop和hive都在linux下解压一下,通过linux虚拟机下输入schematool命令简单搞定(前提是,你要将对的hive-site.xml拷贝到conf下面,当然你可能还会缺少mysql jdbc driver(*^_^*)):
bin/schematool -dbType mysql -initSchema
4、这时就能在windows下面直接启动metastore服务了:
bin/hive.cmd --service metastore
5、我们可以通过将hive-site.xml拷贝到spark安装目录的conf下后,启动spark-shell,输入下面的命令来验证是否配置成功:
scala> spark.conf.get("spark.sql.catalogImplementation")
res0: String = hive
你可能需要设置一些HADOOP_HOME,JAVA_HOME等环境变量,本文不是给出最详尽的说明,而是一个指引性的文章,这些希望你能自己遇到后解决。
Spark standalone集群搭建
spark standalone集群的搭建很简单,而且可以直接启动多个worker,这样实现1 master、2 workers的环境,因为worker之间的交互也是我们要关注的。
下面给一个简单的master和worker的windows启动脚本,请放置在bin目录下。
start-master.cmd
@echo off
cmd /V /E /C ""%~dp0spark-class2.cmd" org.apache.spark.deploy.master.Master"
start-worker.cmd
@echo off
cmd /V /E /C ""%~dp0spark-class2.cmd" org.apache.spark.deploy.worker.Worker --cores 4 --memory 4g spark://local.win:7077"
你需要修改local.win为master所在主机的ip或主机名。通过这两个脚本,能更快速的启动集群。
IDEA开发环境的搭建
我们使用idea来直接提交spark任务,这个时候driver实际上就是idea启动的java程序,main函数被直接执行了。这与使用spark-submit有很大的不同,它给你开发调试带来很大的方便。
搭建IDEA下Spark的开发环境,与普通的maven项目并无差别(我习惯于maven多过于sbt),你要注意的是配置合适的java和scala库。同样maven项目中的hadoop依赖需要和安装的一致,否则会遇到奇怪的问题。spark 3.1.2默认的hadoop依赖为3.x,可以通过exclusion后加入指定的hadoop-client库解决,是的,只需要client即可。
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_${scala.version}</artifactId>
<version>${spark.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
</exclusion>
</exclusions>
</dependency>
然后就是,开发时指定搭建好的spark standalone集群,同时开启hive metastore,你需要将hive-site.xml放置在resources下面。如果是简单的spark程序,不需要上传jar包,但是更多的时候,你需要在SparkConf里通过addJars来加入你开发的jar包,jar包在Executor执行task时会需要。
参考如下:
object TestSQL {
def main(args: Array[String]): Unit = {
// val conf = new SparkConf().setMaster("local[*]").setAppName("testSQL")
val conf = new SparkConf().setMaster("spark://local.win:7077").setAppName("testSQL")
// .setJars(List("./out/artifacts/test_jar/test.jar")) // 非本地模式需要手动添加应用jar包,没有使用闭包/自定义函数等时可以不用
val spark = SparkSession.builder().config(conf).enableHiveSupport().getOrCreate()
spark.sql("select * from t1").show()
spark.stop()
}
}
为了顺利的idea里提交任务到standalone集群上运行,上面提到的scala版本问题一定要非常注意。