连接Zookeeper的方法如下:
复制代码
public static Configuration hBaseConfiguration = null;
public static HBaseAdmin hBaseAdmin = null;
public static void init() {
hBaseConfiguration = HBaseConfiguration.create();
try {
hBaseAdmin = new HBaseAdmin(hBaseConfiguration);
} catch (Exception e) {
throw new HbaseRuntimeException(e);
}
}
复制代码
这里其实是将两个默认的配置文件加进来了,对于相同的配置项,后者会覆盖前者
conf.addResource("hbase-default.xml");
conf.addResource("hbase-site.xml");
可是总是报下面的错:
An error is preventing HBase from connecting to ZooKeeper
Caused by: java.io.IOException: Unable to determine ZooKeeper ensemble
断点跟踪到Zookeeper的源码发现是ZKUtil类的connect方法抛出的异常,
复制代码
Watcher watcher, final String descriptor)
throws IOException {
if(ensemble == null) {
throw new IOException("Unable to determine ZooKeeper ensemble");
}
int timeout = conf.getInt("zookeeper.session.timeout", 180 * 1000);
LOG.debug(descriptor + " opening connection to ZooKeeper with ensemble (" +
ensemble + ")");
return new ZooKeeper(ensemble, timeout, watcher);
}
复制代码
上述代码表明是没有读取到Zookeeper集群的地址,这个地址是在ZooKeeperWatcher的构造函数中读取的:
this.quorum = ZKConfig.getZKQuorumServersString(conf);
继续跟下去,发现配置信息是makeZKProps方法读取出来的,
复制代码
// it and grab its configuration properties.
ClassLoader cl = HQuorumPeer.class.getClassLoader();
final InputStream inputStream =
cl.getResourceAsStream(HConstants.ZOOKEEPER_CONFIG_NAME);
if (inputStream != null) {
try {
return parseZooCfg(conf, inputStream);
} catch (IOException e) {
LOG.warn("Cannot read " + HConstants.ZOOKEEPER_CONFIG_NAME +
", loading from XML files", e);
}
}
复制代码
看到这里才恍然大悟,它会首先去检查CLASSPATH下是否有zoo.cfg文件,如果有,则将其中的配置项读取出来作为Zookeeper的配置项,而此时就会完全不顾 hbase-default.xml和hbase-site.xml这两个配置文件了!