项目中用到hbase,有时候可能会报一些异常,比如java.io.IOException: Unable to determine ZooKeeper ensemble 等等,当出现这个问题时,某某说是项目中用到线程池的问题导致的,但查看异常之后,并非跟啥线程池有关系,异常信息如下:
java.io.IOException: Unable to determine ZooKeeper ensemble at org.apache.hadoop.hbase.zookeeper.ZKUtil.connect(ZKUtil.java:120) at org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher.<init>(ZooKeeperWatcher.java:165) at org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher.<init>(ZooKeeperWatcher.java:134) at org.apache.hadoop.hbase.client.ZooKeeperKeepAliveConnection.<init>(ZooKeeperKeepAliveConnection.java:43) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.getKeepAliveZooKeeperWatcher(HConnectionManager.java:1710) at org.apache.hadoop.hbase.client.ZooKeeperRegistry.isTableOnlineState(ZooKeeperRegistry.java:100) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.isTableDisabled(HConnectionManager.java:879) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.relocateRegion(HConnectionManager.java:1032) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegionInMeta(HConnectionManager.java:1255) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegion(HConnectionManager.java:1059) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.locateRegion(HConnectionManager.java:1016) at org.apache.hadoop.hbase.client.HTable.finishSetup(HTable.java:326) at org.apache.hadoop.hbase.client.HTable.<init>(HTable.java:310) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.getTable(HConnectionManager.java:712) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.getTable(HConnectionManager.java:694) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.getTable(HConnectionManager.java:684) at net.shgaoxin.eastdaytoprankblack.db.HbaseConnEastdayminisite.gethbasetable(HbaseConnEastdayminisite.java:80) at net.shgaoxin.eastdaytoprankblack.db.LinkDBeastdayminisite.checkpageinhbase(LinkDBeastdayminisite.java:195) at net.shgaoxin.eastdaytoprankblack.db.HbasePersistent.execute(HbasePersistent.java:41) at net.shgaoxin.eastdaytoprankblack.servlet.ToprankblackServlet.doPost(ToprankblackServlet.java:61) at net.shgaoxin.eastdaytoprankblack.servlet.ToprankblackServlet.doGet(ToprankblackServlet.java:33) at javax.servlet.http.HttpServlet.service(HttpServlet.java:624) at javax.servlet.http.HttpServlet.service(HttpServlet.java:731) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
查看源码ZooKeeperWatcher类:
1 public ZooKeeperWatcher(Configuration conf, String identifier, 2 Abortable abortable, boolean canCreateBaseZNode) 3 throws IOException, ZooKeeperConnectionException { 4 this.conf = conf; 5 // Capture a stack trace now. Will print it out later if problem so we can 6 // distingush amongst the myriad ZKWs. 7 try { 8 throw new Exception("ZKW CONSTRUCTOR STACK TRACE FOR DEBUGGING"); 9 } catch (Exception e) { 10 this.constructorCaller = e; 11 } 12 this.quorum = ZKConfig.getZKQuorumServersString(conf); 13 // Identifier will get the sessionid appended later below down when we 14 // handle the syncconnect event. 15 this.identifier = identifier; 16 this.abortable = abortable; 17 setNodeNames(conf); 18 this.recoverableZooKeeper = ZKUtil.connect(conf, quorum, this, identifier); 19 if (canCreateBaseZNode) { 20 createBaseZNodes(); 21 } 22 }
从源码中可得知,zookeeper地址存在问题,然后在看看ZKConfig类额方法:
1 public static String getZKQuorumServersString(Properties properties) { 2 String clientPort = null; 3 List<String> servers = new ArrayList<String>(); 4 5 // The clientPort option may come after the server.X hosts, so we need to 6 // grab everything and then create the final host:port comma separated list. 7 boolean anyValid = false; 8 for (Entry<Object,Object> property : properties.entrySet()) { 9 String key = property.getKey().toString().trim(); 10 String value = property.getValue().toString().trim(); 11 if (key.equals("clientPort")) { 12 clientPort = value; 13 } 14 else if (key.startsWith("server.")) { 15 String host = value.substring(0, value.indexOf(':')); 16 servers.add(host); 17 try { 18 //noinspection ResultOfMethodCallIgnored 19 InetAddress.getByName(host); 20 anyValid = true; 21 } catch (UnknownHostException e) { 22 LOG.warn(StringUtils.stringifyException(e)); 23 } 24 } 25 } 26 27 if (!anyValid) { 28 LOG.error("no valid quorum servers found in " + HConstants.ZOOKEEPER_CONFIG_NAME); 29 return null; 30 } 31 32 if (clientPort == null) { 33 LOG.error("no clientPort found in " + HConstants.ZOOKEEPER_CONFIG_NAME); 34 return null; 35 } 36 37 if (servers.isEmpty()) { 38 LOG.fatal("No servers were found in provided ZooKeeper configuration. " + 39 "HBase must have a ZooKeeper cluster configured for its " + 40 "operation. Ensure that you've configured '" + 41 HConstants.ZOOKEEPER_QUORUM + "' properly."); 42 return null; 43 } 44 45 StringBuilder hostPortBuilder = new StringBuilder(); 46 for (int i = 0; i < servers.size(); ++i) { 47 String host = servers.get(i); 48 if (i > 0) { 49 hostPortBuilder.append(','); 50 } 51 hostPortBuilder.append(host); 52 hostPortBuilder.append(':'); 53 hostPortBuilder.append(clientPort); 54 } 55 56 return hostPortBuilder.toString(); 57 }
基本上可以确定是ZooKeeper对应的地址不可访问。不是啥线程池的问题,跟程序中用到线程池没半毛钱关系,这种说法可怕啊..........