问题背景
hive 与 hbase 集成的时候,无论是hive 中读取hbase 表的数据还是hive中创建hbase表,首先创建表都能成功,但是查询Hive 表中的数据就会报Java空指针错误,报错情况如下图所示。
定位问题
光上面的错误信息你很难去判断是哪里出错了,从而无法定位问题,解决错误。幸运的是我们配置了hive 的日志目录,所以我们可以去查看hive的详细日志,于是我进到hive的日志目录查看日志,日志显示如下
java.io.IOException: java.lang.NullPointerException
at org.apache.hadoop.hive.ql.exec.FetchOperator.getNextRow(FetchOperator.java:634)
at org.apache.hadoop.hive.ql.exec.FetchOperator.pushRow(FetchOperator.java:532)
at org.apache.hadoop.hive.ql.exec.FetchTask.fetch(FetchTask.java:137)
at org.apache.hadoop.hive.ql.Driver.getResults(Driver.java:1570)
at org.apache.hadoop.hive.cli.CliDriver.processLocalCmd(CliDriver.java:289)
at org.apache.hadoop.hive.cli.CliDriver.processCmd(CliDriver.java:221)
at org.apache.hadoop.hive.cli.CliDriver.processLine(CliDriver.java:431)
at org.apache.hadoop.hive.cli.CliDriver.executeDriver(CliDriver.java:800)
at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:694)
at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:633)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.main(RunJar.java:212)
Caused by: java.lang.NullPointerException
at org.apache.hadoop.net.DNS.reverseDns(DNS.java:92)
at org.apache.hadoop.hbase.mapreduce.TableInputFormatBase.reverseDNS(TableInputFormatBase.java:228)
at org.apache.hadoop.hbase.mapreduce.TableInputFormatBase.getSplits(TableInputFormatBase.java:191)
at org.apache.hadoop.hive.hbase.HiveHBaseTableInputFormat.getSplitsInternal(HiveHBaseTableInputFormat.java:422)
at org.apache.hadoop.hive.hbase.HiveHBaseTableInputFormat.getSplits(HiveHBaseTableInputFormat.java:358)
at org.apache.hadoop.hive.ql.exec.FetchOperator.getRecordReader(FetchOperator.java:413)
at org.apache.hadoop.hive.ql.exec.FetchOperator.getNextRow(FetchOperator.java:559)
... 14 more
文字版的排版比较乱,不利于一眼查看问题的所在,来个图片版的
可以清楚的看到是因为DNS反向解析错误,查看hbase的相关源码发现hbase会使用ip地址到域名的反向解析。于是我通过nslookup 10.5.150.151
发现确实反向解析不成功,那怎么办?出现问题就要解决问题,于是我打算自己搭建一个DNS Server
解决问题
问题的原因也找到了,解决办法也找到了,那面下面开始动手解决问题—搭建DNS服务器。由于我选用的DNS Server 是Centos7操作系统,所以第一步是下载DNS 服务安装包,由于我嫌弃国内镜像速度慢,于是我打算换掉Centos7自带的Yum源,换成阿里云的。
1. 备份
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
2. 下载新的CentOS-Base.repo 文件
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
3. 运行yum makecache生成缓存
yum makecache
接下来就开始正式搭建DNS Server了,首先安装bind 包
yum -y install bind*
配置DNS Server,修改/ect/named.conf文件
接下来修改/etc/named.rfc1912.zones 文件,加入下面这些
【注】hadoop03 是我的主机名,主机名取的不太好,标准的应该是xxx.公司网址
接下来就是创建正向解析文件和反向解析文件了
cp /var/named/named.localhost /var/named/hadoop03.zone
hadoop03.zone的内容如下:
$TTL 1D
@ IN SOA hadoop03. root (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS hadoop03.
A 10.5.151.251
AAAA ::1
反向解析文件
cp /var/named/named.localhost /var/named/10.5.zone
hadoop03.zone的内容如下:
$TTL 1D
@ IN SOA hadoop03. root (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
@ IN NS hadoop03.
251.151 IN PTR hadoop03
148.150 IN PTR hadoop02
149.150 IN PTR hadoop01
由于主要问题是DNS反向解析出现问题,所以这里只要重点配置反向解析文件,hadoop01,hadoop02,hadoop03是集群中其他的机器的主机名,这样DNS Server大致就搭建好了,接下来进行一些收尾工作,设置DNS 服务开机启动
systemctl enable named.service
修改每台机器的DNS Server
vim /etc/resolv.conf
追加一下一行
namseserver 10.5.151.251
[注意] 这只是临时测试,建议最好修改 /etc/sysconfig/network-scripts 下ifcfg-网卡名字 的设置,因为resolv.conf的DNS server都是从网卡的配置文件读取的,自动生成的。如果我们关机重启之后namseserver 10.5.151.251 就会消失,因此为了一劳永逸,我建议还是把DNS Server 配置在 网卡的配置文件里,这里略去配置过程。
启动DNS服务
systemctl start named.service
测试DNS配置的是否OK
nslookup 10.5.151.251
出现如下结果说明DNS配置成功
在hive 中测试,删除之前创建的表
drop table weblogs
重新创建表
create external table weblogs(id string,datatime string,userid string,searchname string,retorder string,cliorder string,cliurl string) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES("hbase.columns.mapping" = ":key,info:datatime,info:userid,info:searchname,info:retorder,info:cliorder,info:cliurl") TBLPROPERTIES("hbase.table.name" = "weblogs");
从hive 中读取hbase的数据
select * from weblogs;
可以读取数据,不再报空指针,完美解决问题!!!