异常
异常如下:
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();
}
}
}