如何解决java接口访问ZooKeeper时的connectionloss错误

时间:2022-03-01 08:27:29

常见错误日志如下:
org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss

1. 原因:

是因为ZooKeeper建立连接时采用异步操作,连接操作后并不能保证ZK连接已成功。如果在ZK连接成功前的这个小时间窗口去访问ZK,就会碰到如上错误。

2. 解决思路

我们在新建ZK连接后要等一段时间,保证连接成功后再访问ZK。

3. 网上比较赞同的解决方案:

  主要利用两个java类:

 (1)java.util.concurrent.CountDownLatch:

        一个同步辅助类,类似倒数计数,直到计数器为0时才能对资源“解锁”。未解锁前等待该资源的进程只能被阻塞。

        主要方法:
            public CountDownLatch(int count);                           /* 构造函数,参数指定计数次数 */
            public void countDown();                                           /* 当前线程调用此函数,则计数减一 */
            public void await() throws InterruptedException;      /* 此函数会一直阻塞当前线程,直到计时器的值为0为止 */

 (2)org.apache.zookeeper.Watcher

        ZooKeeper有一个很有用的功能,就是集群上每一个变化都可以通知到自定义的Watchcer。

4. 参考代码模板( 仅是模板,未经编译运行过,需稍作补充修改):

****************************************************************************************************************************
import
java.util.concurrent.CountDownLatch;
import java.io.IOException;
import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooDefs.Ids;

public class ZkClient {

    public static void waitUntilConnected(ZooKeeper testZooKeeper, CountDownLatch testLatch) {
        if(testZooKeeper.getState() == States.CONNECTING) {
            try {
                testLatch.await();
            } catch (InterruptedException err) {
                System.out.println("Latch exception");
            }
        }
    }


    static class ConnectedWatcher implements Watcher {
        private CountDownLatch connectedLatch;

        ConnectedWatcher(CountDownLatch connectedLatch) {

            this.connectedLatch = connectedLatch;  /* CountDownLatch实例初始化时设为1即可 */

        }

        @Override
        public void process(WatchedEvent event) {

            if (event.getState() == KeeperState.SyncConnected) {

                connectedLatch.countDown(); /* ZK连接成功时,计数器由1减为0 */

            }
        }
    }


    public static void main(String args[]) throws IOException, KeeperException, InterruptedException {
        try {
            CountDownLatch sampleLatch = new CountDownLatch(1);
            Watcher sampleWatcher = new ConnectedWatcher (sampleLatch);
            zk = new ZooKeeper("127.0.0.1:2181", 30, sampleWatcher);
            waitUntilConnected(zk, sampleLatch);    /* 只有当ZK链接成功(状态为 SyncConnected)时,此函数调用才结束 */

            /*接下来就可以继续ZK访问了,避免因为ZK未连接成功时的访问出错 */
            ...
        } catch(Exception err) {
            System.out.println(err);
        }
    }

}

****************************************************************************************************************************


IT人的微信自媒体--- 杰天空, 走在寻找创意的路上
发掘创意,点缀生活,品味人生。
请搜索微信订阅号: jksy_studio  ,或者微信扫描下图二维码添加关注

如何解决java接口访问ZooKeeper时的connectionloss错误
杰天空静候您的光临。