环境搭建
- jdk1.8.0_144
- hadoop-2.7.3
- apache-hive-2.3.3-bin
- spark-2.0.0-bin-hadoop2-without-hive
特别注意:Hive on Spark对Hive和Spark的版本要求比较严格,必须选用特定搭配的版本,如此处的hive2.3.x和spark2.0.0兼容,具体的版本关系可参考官网:https://cwiki.apache.org/confluence/display/Hive/Hive+on+Spark:+Getting+Started
Spark源码编译
为什么需要重新编译源码,不能使用官方提供的编译后的程序
默认的Spark中包含spark-sql模块,该模块中包含hive相关的jar包,用于spark-sql访问hive,这些hive的jar包会和此时我们需要整合的hive版本冲突。因此,如果需要使用Hive on Spark,需要将spark-sql中和hive相关的jar包去除,所以需要对源码重新编译,编译后的spark是不能使用spark-sql功能的。
下载Spark源码
从GitHub上下载Spark源码,链接:https://github.com/apache/spark/releases
编译源码
以spark-2.0.0为例
- 解压spark-2.0.0.tar.gz
tar -xzvf spark-2.0.0.tar.gz
- 进入spark-2.0.0目录
cd /root/tool/spark-2.0.0
- 调用如下命令,对spark源码进行编译
./dev/make-distribution.sh --name "hadoop2-without-hive" --tgz "-Pyarn,hadoop-provided,hadoop-2.7,parquet-provided"
- 半个小时左右,源码编译成功,会在源码根目录下生成一个名为spark-2.0.0-bin-hadoop2-without-hive.tgz的压缩文件。
注意:
1.网上很多教程说编译spark源码前,需要先安装maven和scala,但本人在编译过程中,并未手动安装maven和scala,依旧能够编译成功,后来查资料发现,spark源码中自带maven和scala,因此无需手动安装;
2.刚开始编译时,会卡在类似如下日志片段的地方,本人终止了编译命令,又重新执行编译命令,来回试了两次,就可以继续往下进行。估计是编译命令执行到此处时,确实进行了比较耗时的操作,由于虚拟机性能瓶颈,造成编译命令卡住的假象,建议耐心等待。
++ /opt/spark213_github/spark-2.1.3/build/mvn help:evaluate -Dexpression=project.version -Pyarn,hadoop-provided,hadoop-2.7,parquet-provided ++ tail -n 1 ++ grep -v INFO
配置Spark
- 解压spark-2.0.0-bin-hadoop2-without-hive.tgz
tar -xzvf spark-2.0.0-bin-hadoop2-without-hive.tgz -C /root/training
- 进入spark-2.0.0-bin-hadoop2-without-hive下的conf目录,在spark-env.sh中添加如下配置信息:
export JAVA_HOME=/root/training/jdk1.8.0_144
export SPARK_MASTER_HOST=bigdata111 # 主节点host
export SPARK_MASTER_PORT=7077 # 主节点端口号
export SPARK_DIST_CLASSPATH=$(/root/training/hadoop-2.7.3/bin/hadoop classpath)
export HADOOP_HOME=/root/training/hadoop-2.7.3
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop/
export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop/
- HADOOP_CONF_DIR和YARN_CONF_DIR:指定Hadoop配置文件的路径,用来配置Spark On Yarn;
- SPARK_DIST_CLASSPATH:指定Hadoop的classpath,hive启动spark任务时会将hadoop的classpath加进来
- 在HDFS上创建目录spark-jars,并将spark-2.0.0-bin-hadoop2-without-hive下jars目录下的所有jar包上传至HDFS中;记住该目录,在Hive中会配置此参数。目的:让YARN缓存spark依赖的jar包,这样hive在执行Spark任务时,就无需每次都需要分发这些jar包,提高程序执行的效率。
hdfs dfs -mkdir /spark-jars
hdfs dfs -put jars/*.jar /spark-jars
- 在HDFS上创建目录sparkeventlog,用于保存日志文件;记住该目录,在Hive中会配置此参数。
hdfs dfs -mkdir /sparkeventlog
配置Hive
在Hive on MR的基础上,再进行如下配置
- 将spark-2.0.0-bin-hadoop2-without-hive/jars目录下的scala-library、spark-core、spark-network-common三个jar包拷贝至hive的lib目录
cd /root/training/spark-2.0.0-bin-hadoop2-without-hive/jars
cp scala-library-2.11.8.jar spark-core_2.11-2.0.0.jar spark-network-common_2.11-2.0.0.jar /root/training/hive-2.3.3/lib/
- 在$HIVE_HOME/conf/hive-site.xml文件中添加如下配置参数:
<!--指定hive的执行引擎为spark-->
<property>
<name>hive.execution.engine</name>
<value>spark</value>
</property>
<!-- -->
<property>
<name>hive.enable.spark.execution.engine</name>
<value>true</value>
</property>
<!--指定spark的文件目录-->
<property>
<name>spark.home</name>
<value>/root/training/spark-2.0.0-bin-hadoop2-without-hive</value>
</property>
<!--指定spark运行在yarn上-->
<property>
<name>spark.master</name>
<value>yarn-client</value>
</property>
<!--启动spark的日志打印功能-->
<property>
<name>spark.eventLog.enabled</name>
<value>true</value>
</property>
<!--指定spark日志保存的路径-->
<property>
<name>spark.eventLog.dir</name>
<value>hdfs://bigdata111:9000/sparkeventlog</value>
</property>
<!--指定yarn缓存spark jar包的路径-->
<property>
<name>spark.yarn.jars</name>
<value>hdfs://bigdata111:9000/spark-jars/*</value>
</property>
<!---->
<property>
<name>spark.serializer</name>
<value>org.apache.spark.serializer.KryoSerializer</value>
</property>
<!--指定spark执行器占用的内存空间-->
<property>
<name>spark.executor.memeory</name>
<value>512m</value>
</property>
<!--指定spark驱动占用的内存空间-->
<property>
<name>spark.driver.memeory</name>
<value>512m</value>
</property>
注意:对hive-site.xml文件进行配置,网上(包括官网)还有一种说法,如下图。但不知道为何,将参数设置在spark-defaults.conf中,不起作用,只有转为xml格式,再hive-site.xml中设置,才奏效
配置YARN
为$HADOOP_HOME/etc/hadoop/yarn-site.xml添加如下参数:
<!--使用公平调度策略-->
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
</property>
<!--禁用虚拟内存的检查-->
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
如果不设置yarn.nodemanager.vmem-check-enabled参数,hive在执行spark任务时,会抛出异常,详细案例见最后一节,问题汇总。
测试Hive on Spark
启动hive客户端,如果是第一次启动hive,在此之前还需要对MySQL数据库执行初始化(schematool -dbType mysql -initSchema)
如果上述步骤配置成功,此处在启动hive的过程中,不会打印出如下信息:
Hive-on-MR is deprecated in Hive 2 and may not be available in the future versions. Consider using a different execution engine (i.e. spark, tez) or using Hive 1.X releases.
因为这句信息是用来提示使用者Hive on MR已经过时,建议更换引擎为spark或tez。
创建数据表,并导入数据。执行如下SQL(可触发MR程序):
select count(*) from xxx;
正常情况下,hive能够将spark作为底层的执行引擎,并且可在yarn的web页面查询到相关记录,任务命名为Hive on Spark,任务的类型为SPARK,如下图所示:
hive客户端的查询结果如下图所示:
注意:
1.hive在处理较复杂的SQL时,会转化为spark任务,所有的这些spark任务实际上是作为一个大的任务运行在YARN中,命名为Hive on Spark。并不是hive执行一次spark任务,就在YARN上提交一个新的任务;
2.Hive on Spark,无需先手动启动spark,因为此时spark是基于yarn,交由yarn进行管理调度;
Hive on Spark对比Hive on MR
同一条SQL语句:
select deptno,sum(sal) from emp group by deptno;
hive on spark
hive on mr
在yarn中hive on mr和hive on spark的对比
问题汇总
hive中执行SQL指令转为spark程序时,运行失败
hive客户端日志如下:
Yarn控制台显示如下:
该错误是由于是Yarn的虚拟内存计算方式导致,可在yarn-site.xml文件中,将yarn.nodemanager.vmem-check-enabled设置为false,禁用虚拟内存检查。
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
参考网址
https://blog.csdn.net/Dante_003/article/details/72867493
https://blog.csdn.net/mousezhengph/article/details/79026063