使用客户端API连接zookeeper报错“ConnectionLossException: KeeperErrorCode = ConnectionLoss for /“

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用客户端API连接zookeeper报错“ConnectionLossException: KeeperErrorCode = ConnectionLoss for /“相关的知识,希望对你有一定的参考价值。

异常

异常如下:

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();
        
    

参考资料:

以上是关于使用客户端API连接zookeeper报错“ConnectionLossException: KeeperErrorCode = ConnectionLoss for /“的主要内容,如果未能解决你的问题,请参考以下文章

hbase连接java时,zookeeper总是连接不上,但是确实已经启动,每次连接,都报错

ZooKeeper客户端源码(零)——客户端API使用

ZooKeeper客户端源码(零)——客户端API使用

ZooKeeper客户端源码(零)——客户端API使用

ZooKeeper客户端源码(零)——客户端API使用

06_zookeeper原生Java API使用