转载

Hive中带条件查询时报Class org.apache.hive.hcatalog.data.JsonSerDe not found的错误及解决办法

数据计算平台重新搭建成功后,一切顠红,看起来心情就是舒畅,放个截图让心情爽一把:

Hive中带条件查询时报Class org.apache.hive.hcatalog.data.JsonSerDe not found的错误及解决办法

后续当然需要做一些验证性的工作,以确保安装成功后一切都是执行OK的。

先放一些测试的JSON文件到HDFS的/tmp/test_json目录下,然后打开HUE界面,进行Hive SQL执行窗口,先创建一个基于JSON文件的外部表:

CREATE TABLE json_table(`_id` STRING,`key` string, value string)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS TEXTFILE
location '/tmp/test_json';

然后执行一下查询语句:

SELECT * from json_table;

结果可以正常展示,然后再执行一个带条件的查询语句:

SELECT * from json_table where `_id`='key1';

此时就报错了,Hive的日志中体现出来的错误大致如下:

java.lang.RuntimeException: Map operator initialization failed: org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassNotFoundException: Class org.apache.hive.hcatalog.data.JsonSerDe not found

根据排查,该类存在于hive的hcategory包中,通过查找,其在我服务器的准确位置为/opt/cloudera/parcels/CDH-5.14.2-1.cdh5.14.2.p0.3/jars/hive-hcatalog-core-1.1.0-cdh5.14.2.jar。

这个错误虽然是Hive日志中暴露出来的,但是很显然Hive中肯定是已经引入了这个包的,要不然第一条不带条件的语句是不可能执行成功的,这个应该是Hive调用的其它应用报出来的。

经过分析,Hive在执行不带条件的SQL语句时,如下:

select * from xx;
select * from xx limit 100;

HIVE为了加快执行速度,是通过 Fetch task 模式执行的,而没有使用MR模式,因为这里没有涉及到复杂的计算,纯粹只是为了获取数据,这样处理可以节约处理的时间,也减少将其转换为MR模式的内存和CPU开销。

MR是通过YARN来最终执行的,而YARN中配置的MR执行引擎是Spark,因而需要在YARN和Spark中增加hive-hcatalog-core-1.1.0-cdh5.14.2.jar的引用,话说虽然简单,但是执行起来还是经过了一些折腾,特别是给Spark增加Jar包的引入。

以下是给Spark增加lib包的失败尝试:

1.在${CDH_HOME}/lib/spark/lib目录下建立jar包的软链接;
2.把jar包拷贝到${CDH_HOME}/lib/spark/lib目录下;
3.在${CDH_HOME}/lib/spark/conf/classpath.txt中增加jar包路径;
4.在${CDH_HOME}/lib/spark/conf/spark-env.sh中增加jar包路径的路径;

每次做了以上的修改后,然后在CM上面重启spark,都希望这次修改能够生效,把依赖的Jar包加到Spark的运行环境中,可以每次回到命令行查看spark的classpath都没有将需要依赖的jar加进去,每次都伤心。

正在无解之时,无意中查看spark的启动参数时,发现spark使用的配置参数路径并不是我修改的spark的配置文件的路径,如下:    

--properties-file /run/cloudera-scm-agent/process/797-spark_on_yarn-SPARK_YARN_HISTORY_SERVER/spark-conf/spark-history-server.conf

而我修改的spark的配置文件路径是:    

${CDH_HOME}/lib/spark/conf/

终于知道是CM的原因了,因为CM会在重新生成配置文件,即使${CDH_HOME}/lib/spark/conf/这个路径下面的配置文件也是根据CM中spark的配置生成的,即使在这个目录下做了修改,也会被CM给重写覆盖掉,测试的结果并不是CM每次都会重写这下面的配置文件,并不是每次通过CM重启spark这下面的配置文件都会修改,所以才不那么容易发现问题。

正确的解决办法:

1.在Spark中增加新的Jar包

在CM的spark配置文件所在页面,在“configuration->Filter->Category->Advanced->Spark Service Advanced Configuration Snippet (Safety Valve) for spark-conf/spark-env.sh”配置项中增加以下内容:

#以下脚本会写入的spark-env.sh中,是把外部目录下面的所有jar全部都加到spark的classpath
#/data/share_libs是共享外部类存放的路径,每台服务器上都有这个目录,hive-hcatalog-core-1.1.0-cdh5.14.2.jar已经在这下目录下建立了软链接到真实的文件

export SHARE_JAR_HOME=/data/share_libs
for f in $SHARE_JAR_HOME/*.jar 
do
SHARE_JAR_CLASSPATH=$f:$SHARE_JAR_CLASSPATH
done
export SHARE_JAR_CLASSPATH
export SPARK_DIST_CLASSPATH=$SHARE_JAR_CLASSPATH$SPARK_DIST_CLASSPATH

加上以上脚本重启spark后,终于可以在命令行看到spark的classpath中包括了hive-hcatalog-core-1.1.0-cdh5.13.1.jar依赖jar包,spark本身已经不会报错找不到依赖的类了。

2.给Yarn增加

找到yarn所在的目录${CDH_HOME}/lib/hadoop-yarn,在里面建立hive-hcatalog-core-1.1.0-cdh5.14.2.jar文件的软链接,每台服务器的yarn目录都建立这个软链接,然后重启yarn服务器,这个再执行终于不会报错了。

原文  https://blog.csdn.net/fenglibing/article/details/80437246
正文到此结束
Loading...