即使达到超时限制,Zookeeper也不会过期

时间:2019-02-22 10:36:17

标签: java apache-zookeeper

我在程序中观察到一个奇怪的问题,我正在使用一个独立的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文件。我在做什么错,为什么我的会话永不过期?

1 个答案:

答案 0 :(得分:0)

好吧,我发现了问题(我想)。问题似乎是,当我依次关闭Zookeeper服务器以模拟会话到期并且客户端保持重新连接时,但我错过的要点是Zookeeper服务器管理了会话到期,并且当我关闭它并再次打开时一段时间后,它将为关闭的客户端恢复尝试连接的客户端的会话时间,这就是会话似乎永不过期的原因。为证明起见,我尝试从另一台计算机上获取客户端代码,然后关闭其连接,同时保持Zookeeper服务器一直处于运行状态,一段时间后再次重新连接客户端,boom在默认观察程序中收到会话过期通知,并获得了sessionexpired异常。