zookeeper的踩坑之路(一)

zookeeper Java客户端连接问题

具体参考文章 ConnectionLoss异常解决

zookeeper客户端连接特点:zookeeper建立连接时采用异步操作,连接操作后并不能保证zookeeper已连接成功,如果在zookeeper连接成功前访问相应节点,会出现ConnectionLoss错误。

解决思路:在新建zookeeper连接后,保证连接成功后再访问zookeeper。

具体代码:

	public static void waitUntilConnected(ZooKeeper testZooKeeper, CountDownLatch testLatch) {
        if (testZooKeeper.getState() == ZooKeeper.States.CONNECTING) {
            try {
                testLatch.await();  //此函数会一直阻塞当前进程,直到计数器的值为0为止
            } catch (Exception e) {
                e.printStackTrace(printWriter);
                System.out.println("Latch exception");
            }
        }
    }

    static class ConnectedWatcher implements org.apache.zookeeper.Watcher {
        private CountDownLatch connectedLatch;

        ConnectedWatcher(CountDownLatch connectedLatch) {
            this.connectedLatch = connectedLatch;  /* CountDownLatch实例初始化时设为1即可 */
        }

        @Override
        public void process(WatchedEvent event) {
            if (event.getState() == Event.KeeperState.SyncConnected) {
                connectedLatch.countDown(); /* ZK连接成功时,计数器由1减为0 */
            }
        }
    }

    /**
     * 初始化zookeeper连接
     */
    public boolean newZookeeperLink() {
        try {
            if (zooKeeper != null && zooKeeper.getState() == ZooKeeper.States.CONNECTED) {
                return true;
            } else {
                destroy();
                CountDownLatch sampleLatch = new CountDownLatch(1);
                Watcher sampleWatcher = new ConnectedWatcher(sampleLatch);
                zooKeeper = new ZooKeeper(zookeeperIPUtil.getIP() + ":" + zookeeperIPUtil.getPort(), 20000, sampleWatcher);
                waitUntilConnected(zooKeeper, sampleLatch);  /*只有当ZK链接成功(状态为SyncConnected)时,此函数调用才结束*/
                logger.info("创建新的zookeeper连接");
                return true;
            }
        } catch (Exception e) {
            logger.info("zookeeper初始化连接失败");
            e.printStackTrace(printWriter);
            logger.error(printWriter.toString());
            return false;
        }
    }

其中使用到了两个类:

  1. java.util.concurrent.CountDownLatch(同步辅助类,类似倒数计数,直到计数器为0时才能对资源“解锁”,未解锁前等待该资源的进程只能被阻塞)
  2. org.apache.zookeeper.Watcher

注意!
不要轻易创建新的zookeeper连接,连接数过多时zookeeper服务端会阻止新的连接生成。
close()方法虽然会关闭zookeeper连接,但是服务端端口会由ESTABLISHED状态变为TIME_WAIT,并且需要一段时间才会完全将此连接删除,当TIME_WAIT状态的连接过多时也会导致服务端阻止新的连接生成的问题。

发布了11 篇原创文章 · 获赞 0 · 访问量 637

猜你喜欢

转载自blog.csdn.net/fate_destiny/article/details/103066932