hbase执行mapreduce任务报dns异常

    在最近的一个项目中有这样一个需求,我们的业务数据是存放在hbase中,一天大概新增五到六百万的,然后我这边需要做一件事是按小时把新增数据加载到impala中,并且数据需要按年月日三个字段分区。

    起初想到的是直接在hive中建立一个表,然后在表上建立一个mapping映射到hbase中的表。但是考虑到分区,业务表中无法提供这些字段,所以另想它法。

    后来想到的是用hbase中提供的TableMapper按时间截扫描(这里不用rowkey原因可以自己思考,时间截会出现的问题,业务那边已经处理),mapreduce任务定时每隔一小时执行一次,每次记录下扫描到的数据的最大和最小时间截。下次依据这个扫描最新数据,然后通过reduce把数据写到hdfs上,最后load到impala上。

    按照上面的思路敲完代码测试的时候,在log中发现一个error,如下图

    通过源码找到报错的地方

InetAddress regionAddress = isa.getAddress();
String regionLocation;
try {
	regionLocation = reverseDNS(regionAddress);
} catch (NamingException e) {
	LOG.warn("Cannot resolve the host name for " + regionAddress + " because of " + e);
	regionLocation = location.getHostname();
}

     抛出异常的方法reverseDNS

private String reverseDNS(InetAddress ipAddress) throws NamingException {
	String hostName = this.reverseDNSCacheMap.get(ipAddress);
	if (hostName == null) {
		hostName = Strings.domainNamePointerToHostName(DNS.reverseDns(ipAddress, this.nameServer));
		this.reverseDNSCacheMap.put(ipAddress, hostName);
	}
	return hostName;
}

    可见hostName的获取是与nameServer有关

this.nameServer = context.getConfiguration().get("hbase.nameserver.address", null);

    而nameServer是从配置(hbase-site.xml)中读取的,hbase.nameserver.address从字面上看是名字服务器的地址,也就是域名服务器。

try {
	regionLocation = reverseDNS(regionAddress);
} catch (NamingException e) {
	LOG.warn("Cannot resolve the host name for " + regionAddress + " because of " + e);
	regionLocation = location.getHostname();
}

    在分析这里,首先根据region所在的regionserver的ip地址去域名服务器中找这个regionserver的主机名,而我们搭建本地集群一般不会去弄个域名服务器什么的,这里当然会找不到,然后才会去hosts文件获取regionserver的主机名。总之这里还是获取到了regionserver的主机名,没有获取到想要的主机域名,不影响mapreduce的执行。

    只有在线上集群,我们可能会申请一个域名,然后为每个节点 的ip映射一个二级域名,然后在hbase-site.xml中配置上hbase.nameserver.address的值为一个域名服务器的ip(比如114.114.114.114)。

    所以不想看到这个error:1、可以自己在一个节点上搭建一个域名服务器,然后再域名服务器的数据库中按hosts的配置添加映射;2、修改源码注释这行代码,覆盖到集群中



猜你喜欢

转载自my.oschina.net/u/1240328/blog/494646