由于CDH5.4.7不支持SPARK-SQL, 因此,需要手动编译spark 1.3.0源码包,添加hive 和hive-thrift支持。
编译的环境为Centos6.5 , 在windows 环境下,用通过cmd模式调用mvn命令编译不过。编译的步骤如下:
1、编译命令:
mvn -Pyarn -Dhadoop
.
version
=
2.6.0
-cdh5
.4.7
-Dscala
-
2.11.8
-Phive -Phive-thriftserver -DskipTests clean package
系统中的scala版本是2.11.8,因此,此处可以将其换成 -Dscala
-
2.11.8
2、设置maven库的镜像地址为:
<mirror>
<id>CN</id>
<mirrorOf>central</mirrorOf>
<name>OSChina Central</name>
<url>http://maven.oschina.net/content/groups/public/</url>
</mirror>
3、
PermGen space不够的异常
export MAVEN_OPTS="-Xmx4g -XX:MaxPermSize=512M
-XX:ReservedCodeCacheSize=512m"
或者
在bin/mvn的后面加上:
MAVEN_OPTS="$MAVEN_OPTS -Xms256m -Xmx
4g -XX:MaxPermSize=
512M
-XX:ReservedCodeCacheSize=
512M"
4、修改protobuf 的版本为系统中protobuf 同一版本(hbase的版本也可以修改下),否则编译成功后,执行运算时会因包冲突导致报错 。
History Server服务也无法启动。
Exception in thread "main" java.lang.VerifyError: class org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$SetReplicationRequestProto overrides final method getUnknownFields.()Lcom/google/protobuf/UnknownFieldSet;
修改后的版本截图为:
5、执行过程中,可能会多次出现卡死的现象,此时终止,重新执行即可。
6、编译完成后,在assembly/target/scala-2.10目录下会生成一个spark-assembly-1.3.0-hadoop2.6.0-cdh5.4.7.jar 的jar文件。
接下来的步骤很关键,涉及到spark的配置及脚本的更改。
7、将生成的jar包拷贝到原来的spark jar目录下。本系统为: /opt/cloudera/parcels/CDH/jars/
需要注意的是,系统中原来的jar文件名为 spark-assembly-1.3.0-cdh5.4.7-hadoop2.6.0-cdh5.4.7.jar,因此,在备份原来的jar文件后,将拷贝进来的jar文件命名为原来的名字(其它地方有软连接至改文件)。
同时,还需要将该jar包复制到其它机器,否则,运行idea 程序spark-sql jar包的时候,会报如下错误:
Exception in thread "main" org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 0.0 failed 4 times, most recent failure: Lost task 0.3 in stage 0.0 (TID 8, hadoop-s2): java.io.InvalidClassException: org.apache.hadoop.hive.metastore.api.Table; local class incompatible: stream classdesc serialVersionUID = -946662244473213550, local class serialVersionUID = 398473631015277182
8、用生成的bin、sbin、conf 目录替换掉相应文件夹,替换前注意备份。
注意:如果不替换掉原来的conf 目录,则会报错误:
Exception in thread "main" java.lang.VerifyError: class org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$SetOwnerRequestProto overrides final method getUnknownFields.()Lcom/google/protobuf/UnknownFieldSet
错误的原因是由于/etc/hive/conf/core-site.xml文件引起的。
因此,解决的办法是删除掉原来的软连接conf, 将编译后生成的conf目录替拷贝到当前目录下,然后将/etc/hive/conf/hive-site.xml 拷贝到conf 目录, 或建立hive-site.xml 到conf 目录的软连接
8、在系统环境中可以直接执行的命令/脚本都放在/usr/bin 目录下。但是,如果直接将spark-sql放置到该目录,则会报错,无法执行。错误如下:
line 53: /usr/bin/utils.sh: 没有那个文件或目录
问题原因在于:
编译后生成的spark-sql脚本运行依赖于脚目录下的utils.sh 。因此,单独拷贝该脚本至/usr/bin目录下,肯定会报错。参考目录下原来的spark-shell脚本,发现它是一个2级链接,指向/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/bin 目录。
再查看/opt/cloudera/parcels/CDH-5.4.7-1.cdh5.4.7.p0.3/bin/spark-shell, 发现它是一个可执行的脚本,而不是链接。可是,将spark-sql直接拷贝到该目录下,仍然报之前同样的错误--路径不对,即使做了软连接,也不行。 但原先的spark-shell脚本却是正常的。问题在于,在spark-shell中,对路径做了非常巧妙的处理:
#!/bin/bash
# Reference: http://*.com/questions/59895/can-a-bash-script-tell-what-directory-its-stored-in
SOURCE="${BASH_SOURCE[0]}"
BIN_DIR="$( dirname "$SOURCE" )"
while [ -h "$SOURCE" ]
# resolve $SOURCE until the file is no longer a symlink
do
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
# if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
BIN_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
done
BIN_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
LIB_DIR=$BIN_DIR/../lib
export HADOOP_HOME=$LIB_DIR/hadoop
# Autodetect JAVA_HOME if not defined
. $LIB_DIR/bigtop-utils/bigtop-detect-javahome
exec $LIB_DIR/spark/bin/spark-shell "$@"
在这段代码中,while 部分完全不起作用,真正起到修改路径的是红色部分。这部分将脚本的路径修改为 /opt/cloudera/parcels/CDH/lib/spark/bin
从而脚本得到正确的执行。
因此,需要仿照spark-shell的内容,新建一个spark-sql 的脚本。同时,在/etc/bin 目录 和 /etc/alternative/ 目录下分别新建spark-sql 的软连接。
至此,所有的工作全部完成!