即使达到超时限制,Zookeeper 也不会使会话过期
Zookeeper not expiring sessions even after timeout limit is reached
我在我的程序中观察到一个奇怪的问题,我正在使用一个独立的 zookeeper 并尝试为客户端模拟一个会话过期事件。现在,就我阅读文档和搜索互联网而言,我相信事件链如下进行。客户端连接到服务器并收到协商的超时,如果在超时期间没有从客户端收到心跳,服务器会使会话过期,即使客户端重新连接,它也会抛出一个会话过期 exception.Now 来模拟这个我已经编写了以下一段代码,但不知何故它工作得很好并且没有抛出会话过期异常。
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
}
我还有一个标准的 zoo.cfg 文件,它随 Zookeeper 一起提供。我做错了什么以及为什么我的会话永不过期?
好吧,我发现了问题(我猜)。问题似乎是当我依次关闭 zookeeper 服务器以模拟会话过期并且客户端继续重新连接但我错过的一点是 zookeeper 服务器管理会话过期以及当我关闭它并再次打开它时一段时间后,它会恢复从关闭时开始尝试连接的客户端的会话时间,这就是会话似乎永远不会过期的原因。为了证明我从另一台机器上尝试了客户端代码,然后关闭了它的连接,同时保持 zookeeper 服务器一直运行,一段时间后再次重新连接客户端并且 boom 在默认观察器中收到会话过期通知并得到 sessionexpired 异常。 .
我在我的程序中观察到一个奇怪的问题,我正在使用一个独立的 zookeeper 并尝试为客户端模拟一个会话过期事件。现在,就我阅读文档和搜索互联网而言,我相信事件链如下进行。客户端连接到服务器并收到协商的超时,如果在超时期间没有从客户端收到心跳,服务器会使会话过期,即使客户端重新连接,它也会抛出一个会话过期 exception.Now 来模拟这个我已经编写了以下一段代码,但不知何故它工作得很好并且没有抛出会话过期异常。
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
}
我还有一个标准的 zoo.cfg 文件,它随 Zookeeper 一起提供。我做错了什么以及为什么我的会话永不过期?
好吧,我发现了问题(我猜)。问题似乎是当我依次关闭 zookeeper 服务器以模拟会话过期并且客户端继续重新连接但我错过的一点是 zookeeper 服务器管理会话过期以及当我关闭它并再次打开它时一段时间后,它会恢复从关闭时开始尝试连接的客户端的会话时间,这就是会话似乎永远不会过期的原因。为了证明我从另一台机器上尝试了客户端代码,然后关闭了它的连接,同时保持 zookeeper 服务器一直运行,一段时间后再次重新连接客户端并且 boom 在默认观察器中收到会话过期通知并得到 sessionexpired 异常。 .