异常

异常如下:

org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:102)
	at org.apache.zookeeper.KeeperException.create(KeeperException.java:54)
	at org.apache.zookeeper.ZooKeeper.getChildren(ZooKeeper.java:2589)
	at org.apache.zookeeper.ZooKeeper.getChildren(ZooKeeper.java:2617)
	at Demo01.main(Demo01.java:34)

错误代码

public class Demo01 {
    // zookeeper集群服务器的连接地址,注意多个服务器地址之间用逗号分隔,但逗号之间不能有任何空格
    private static String connectString = "192.168.88.142:2181,192.168.88.132:2181,192.168.88.139:2181";
    // 会话超时时间
    private static int sessionTimeout = 2000;

    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        /**
         * 第一个参数,是zookeeper集群服务器地址,多个服务器之间用逗号分隔
         * 第二个参数,是会话超时时间
         * 第三个参数,表示监听器
         */
        ZooKeeper zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                // 收到事件通知后的回调函数,即用户的业务逻辑
                System.out.println(watchedEvent.getType() + "-" + watchedEvent.getPath());
            }
        });
        // 再次启动监听
        try {
            List<String> children = zkClient.getChildren("/", true);
            for (String child : children) {
                System.out.println(child);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

原因1

出现这个问题的原因有很多,以下列举下。

zookeeper集群或者节点的防火墙没有关闭,导致无法连接成功。我使用的Linux系统是 CentOS7,所以采用查看防火墙状态的命令是:systemctl status firewalld.service

在这里插入图片描述
如果没有关闭则那么执行 systemctl stop firewalld.service 命令关闭防火墙。

不同Linux系统操作防火墙的命令可能不一样,根据自己的操作系统来。

甚至可以尝试关闭自己Windows系统的防火墙。
在这里插入图片描述

原因2

代码中的连接字符串参数和zookeeper集群中 zoo.cfg 配置文件中配置的节点地址不一样。这个地址有可能是IP地址,有可能是配置的名称,但都应该保持一致。
在这里插入图片描述

原因3

即使用zookeeper原生的客户端API连接时,设置的sessionTimeout时间太短,这个时间必须大于zookeeper配置文件中的一个心跳的时间,如果小于一个心跳的时间,zookeeper给客户端发送心跳的时候客户端还没有收到就已经超时了,永远不会连上。所以设置的超时时间必须很大。

其实我们可以在zookeeper的log目录下查看日志文件,来判断出了什么问题。
在这里插入图片描述通过 tail -n100 zookeeper-root-server-centos7_103.out 命令查看日志文件最后一百行的日志:
在这里插入图片描述如果出现这个日志:Unable to read additional data from client sessionid 0x0, likely client has closed socket 就可以判断是这个原因了。修改 sessionTimeout 超时时间足够大,比如 400000

在这里插入图片描述

正确代码

public class Demo01 {
    // zookeeper集群服务器的连接地址,注意多个服务器地址之间用逗号分隔,但逗号之间不能有任何空格
    private static String connectString = "192.168.88.142:2181,192.168.88.132:2181,192.168.88.139:2181";
    // 会话超时时间
    private static int sessionTimeout = 400000;

    public static void main(String[] args) throws IOException {
        /**
         * 第一个参数,是zookeeper集群服务器地址,多个服务器之间用逗号分隔
         * 第二个参数,是会话超时时间
         * 第三个参数,表示监听器
         */
        ZooKeeper zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                // 收到事件通知后的回调函数,即用户的业务逻辑
                System.out.println(watchedEvent.getType() + "-" + watchedEvent.getPath());
            }
        });
        // 再次启动监听
        try {
            List<String> children = zkClient.getChildren("/", true);
            for (String child : children) {
                System.out.println(child);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

参考资料:

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐