问题背景

hive 与 hbase 集成的时候,无论是hive 中读取hbase 表的数据还是hive中创建hbase表,首先创建表都能成功,但是查询Hive 表中的数据就会报Java空指针错误,报错情况如下图所示。

hive IMetastoreclient 关闭 空指针 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

文字版的排版比较乱,不利于一眼查看问题的所在,来个图片版的

hive IMetastoreclient 关闭 空指针 hive报空指针异常_hive_02


可以清楚的看到是因为DNS反向解析错误,查看hbase的相关源码发现hbase会使用ip地址到域名的反向解析。于是我通过nslookup 10.5.150.151

hive IMetastoreclient 关闭 空指针 hive报空指针异常_hadoop_03


发现确实反向解析不成功,那怎么办?出现问题就要解决问题,于是我打算自己搭建一个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文件

hive IMetastoreclient 关闭 空指针 hive报空指针异常_java_04

接下来修改/etc/named.rfc1912.zones 文件,加入下面这些

hive IMetastoreclient 关闭 空指针 hive报空指针异常_hive_05


【注】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 IMetastoreclient 关闭 空指针 hive报空指针异常_java_06

在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;

hive IMetastoreclient 关闭 空指针 hive报空指针异常_hive_07

可以读取数据,不再报空指针,完美解决问题!!!