问题描述

工作中遇到通过jdbc连接hive服务器(我们是用HiveServer2),获取的中文是乱码的问题。使用beeline有同样的效果,而用hive命令行却能正常显示中文。而写入,读取的文件,都是用的UTF-8,Java环境也都是UTF-8字符集。这是怎么回事?

出现乱码时,交互方式是:Client->jdbc->Hive Server2->Hadoop。而正常显示的Hive命令行的交互是:Hive CLI->Hadoop。 所以基本可以确定乱码问题在 Client->jdbc->Hive Server2 这三个部分的其中一个部分上。

排查

1. Client

Client 是我们自行开发的 Java 应用,经查整个项目一直都是用的 UTF-8 字符集,排查 Client 的编码问题。

2. jdbc

查了很多地方,从HiveServer2 Clients中,一段话提醒了我们:

The JDBC connection URL format has the prefix jdbc:hive2:// and the Driver class is org.apache.hive.jdbc.HiveDriver. Note that this is different from the old HiveServer.

再看第一版本的HiveServer Client,使用的是:

driverName = “org.apache.hadoop.hive.jdbc.HiveDriver“;

看到这两个包,在比对我们疑惑的两个包,一切明朗了:

org.apache.hadoop.hive.jdbc 针对HiveServer1,与我们的场景无关。

org.apache.hive.jdbc 针对HiveServer2,我们需要关注。

如上网络上给出的方案针对HiveServer1,确实不适用我们的场景。 细查 org.apache.hive.jdbc 的类,发现这个版本与HiveServer1 的处理完全不一样了,不是使用 serde,还是直接用了 thrift,其中也没找到编码相关的选项。这条路走到头了。

3. HiveServer2

最后,剩下就是检查HiveServer2使用的字符集了。

系统层面:
shell> locale
LANG=zh_CN.UTF-8
LC_CTYPE=”zh_CN.UTF-8″
LC_NUMERIC=”zh_CN.UTF-8″
LC_TIME=”zh_CN.UTF-8″
LC_COLLATE=”zh_CN.UTF-8″
LC_MONETARY=”zh_CN.UTF-8″
LC_MESSAGES=”zh_CN.UTF-8″
LC_PAPER=”zh_CN.UTF-8″
LC_NAME=”zh_CN.UTF-8″
LC_ADDRESS=”zh_CN.UTF-8″
LC_TELEPHONE=”zh_CN.UTF-8″
LC_MEASUREMENT=”zh_CN.UTF-8″
LC_IDENTIFICATION=”zh_CN.UTF-8″
LC_ALL=
shell> echo $LANG
zh_CN.UTF-8

我们是使用CDH4.5中自带的hive-server2启动脚本启动的hiveserver2服务,看看脚本环境中字符集是怎样的。

/etc/init.d/hive-server2中添加locale命令,重启后却是这样的:

shell> service hive-server2 restart
LANG=
LC_CTYPE=”POSIX”
LC_NUMERIC=”POSIX”
LC_TIME=”POSIX”
LC_COLLATE=”POSIX”
LC_MONETARY=”POSIX”
LC_MESSAGES=”POSIX”
LC_PAPER=”POSIX”
LC_NAME=”POSIX”
LC_ADDRESS=”POSIX”
LC_TELEPHONE=”POSIX”
LC_MEASUREMENT=”POSIX”
LC_IDENTIFICATION=”POSIX”
LC_ALL=
Starting Hive Server2 (hive-server2): [确定]
Hive Server2 is running [确定]

看来hive-server2的运行环境并没有沿用系统层面的环境,针对它进行配置:

在/etc/init.d/hive-server2删除刚添加的locale,然后添加语句:export LANG=zh_CN.UTF-8

这样确保hive-server2的启动会使用指定字符集。

当然,如果使用hive –service hiveserver2命令启动,只要保证环境变量LANG=zh_CN.UTF-8即可。

测试结果,如上设置,重启hive-server2后,乱码问题解决!

小结

最终解决乱码问题只是添加了export LANG=zh_CN.UTF-8,确保hive-server2的运行环境使用的是UTF-8字符集,这样Client,Hive-Server和Hadoop集群都采用了UTF-8,自然不会有乱码存在了。

Done!

参考:
http://wocclyl.blog.163.com/blog/static/4622350420134301120474/