我在程序中观察到一个奇怪的问题,我正在使用一个独立的Zookeeper,并试图为客户端模拟会话过期事件。现在,据我看过文档并浏览了互联网,我相信一系列事件如下。客户端连接到服务器并收到协商的超时,并且如果在超时期间未从客户端收到心跳,则服务器将使会话过期,即使客户端重新连接也会抛出会话过期异常。以下代码,但以某种方式可以正常工作,并且不会引发会话过期异常。
String path = "/SessionId3";
ZooKeeper zoo;
final CountDownLatch connectedSignal = new CountDownLatch(1);
zoo = new ZooKeeper("localhost:2182", 5000, new Watcher() {
public void process(WatchedEvent we) {
if (we.getState() == KeeperState.SyncConnected) {
System.out.println("in connected state");
connectedSignal.countDown();
}
if (we.getState() == KeeperState.Disconnected) {
System.out.println("in disconnected state");
connectedSignal.countDown();
}
if (we.getState() == KeeperState.Expired) {
System.out.println("in expired state");
connectedSignal.countDown();
}
if (we.getType() == Event.EventType.None) {
connectedSignal.countDown();
}
}
});
System.out.println("in watcher");
connectedSignal.await();
long sId = zoo.getSessionId();
System.out.println("sessionId=" + sId);
byte[] sPwd = zoo.getSessionPasswd();
System.out.println("session password=" + Arrays.toString(sPwd));
long sTimeout=zoo.getSessionTimeout();
System.out.println("agreed upon session timeout=" +sTimeout);
zoo.create(path,null,ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
byte[] data=zoo.getData(path, new Watcher()
{
public void process(WatchedEvent we)
{
if(we.getType()==Event.EventType.NodeDeleted)
{
System.out.println("node deleted");
}
}
}, null);
System.out.println("disconnect from zookeeper servers.");
//here i kill my zookeeper server to make client disconnect
Thread.sleep(30000);
System.out.println("session must have expired...");
Thread.sleep(10000);
System.out.println("after sleep awakening");
//starting zookeeper server again to emulate reconnect
Thread.sleep(10000);
Stat stat = zoo.exists(path, false); //expected to get session expired exception but works fine?
if (stat != null)
{System.out.println("fetching children");
List<String> children=zoo.getChildren(path, false);
for(String child:children)
{
System.out.println(child);
byte[] b = zoo.getData(path+"/"+child, false, null);
String dataInString = new String(b, "UTF-8");
System.out.println(dataInString);
}
} else
{
System.out.println("Node does not exists");
}
zoo.close();//triggers the watch set on ephemeral node
}
我还有zookeeper附带的标准zoo.cfg文件。我在做什么错,为什么我的会话永不过期?
答案 0 :(得分:0)
好吧,我发现了问题(我想)。问题似乎是,当我依次关闭Zookeeper服务器以模拟会话到期并且客户端保持重新连接时,但我错过的要点是Zookeeper服务器管理了会话到期,并且当我关闭它并再次打开时一段时间后,它将为关闭的客户端恢复尝试连接的客户端的会话时间,这就是会话似乎永不过期的原因。为证明起见,我尝试从另一台计算机上获取客户端代码,然后关闭其连接,同时保持Zookeeper服务器一直处于运行状态,一段时间后再次重新连接客户端,boom在默认观察程序中收到会话过期通知,并获得了sessionexpired异常。