首页 > 代码库 > ZooKeeper的“会话终止”是这么出现的
ZooKeeper的“会话终止”是这么出现的
转载请注明出处: jiq?钦‘s technical Blog
经过我的测试,得出关于会话终止的下列结论:
客户端创建ZooKeeper实例连接到ZooKeeper服务端,设置会话超时时间为10s。
(1)若强制关闭ZooKeeper服务端(模拟其崩溃),客户端立马收到Disconnected连接断开事件,等待半个小时,再次启动ZooKeeper服务端,客户端收到SyncConnected连接建立事件,在这之前注册的watcher仍然有效,推测临时节点也一样有效。
(2)若断开客户端与服务端的网线(模拟网络断开),客户端立马收到Disconnected连接断开事件,等待11s再次插上网线,客户端收到Expired会话终止事件,之前注册的watcher不再有效,推测临时节点也会删除。
结论:
客户端连接到服务端的会话超时时间由服务端记录,客户端每隔一段时间(小于这个会话时间)向服务端发送心跳,服务端就不会将与这个客户端的会话设置为失效!!!
若服务端自己死掉了,将不给这个会话事件做倒计时,若是客户端关闭或者连接断开,就会进行会话终止倒计时,时间一到将会认定会话失效,认为客户端死掉。
还有一种情况可能出现会话终止:即客户端与服务端网络闪断,然后ZooKeeper客户端会自动从服务端地址列表中选择下一个ZooKeeper服务器进行重连,若这个重连时间超过设定的超时时间,比如10s,也会发送会话超时。
你可能会说重连怎么会超过10s呢?假如你在客户端再会话倒计时还剩7s的时候正要给服务端发送心跳,不幸网络刚好断开,然后选择一个重连,这个重连超过3s,那就超时了。
所以说,客户端开发人员进行ZooKeeper开发时,如果你注册到服务端的watcher以及创建的临时节点至关重要时,你可能不需要担心因为ZooKeeper服务器挂掉导致会话失效,但是一定要防备因为网络断开,然后经过会话超时时间之后又自动重新建立连接的情况,因为这个时候会话终止了!!!
如果网络经常闪断,但是断开时间不长,为求保险,可以讲会话超时时间设置长一点,一般30s。
是否可以设置为无限长,比如几天?
下面附上我的测试程序:
注册了watcher的客户端:
public class ZooKeeperTest implements Watcher { private CountDownLatch latch = new CountDownLatch(1); public ZooKeeper GetConnection() throws Exception { ZooKeeper zk = new ZooKeeper("192.168.1.108:2181", 3000, this); latch.await(); return zk; } @Override public void process(WatchedEvent event ) { System.out.println( "收到事件通知:" + event.getState() +"\n路径是:"+event.getPath()); if (KeeperState.SyncConnected == event.getState() ) { latch.countDown(); } } public static void main(String[] args) throws Exception { ZooKeeperTest obj = new ZooKeeperTest(); ZooKeeper zk = obj.GetConnection(); System.in.read(); zk.close(); } }
首先将ZooKeeper服务器强制关闭,过了很久很久在重新开启,输出如下:
收到事件通知:SyncConnected
路径是:null
收到事件通知:Disconnected
路径是:null
收到事件通知:SyncConnected
路径是:null
然后再跑一下我的修改ZooKeeper节点的程序:
public class NodeChangeTest implements Watcher { private CountDownLatch latch = new CountDownLatch(1); public ZooKeeper GetConnection() throws Exception { ZooKeeper zk = new ZooKeeper("192.168.1.108:2181", 3000, this); latch.await(); return zk; } @Override public void process(WatchedEvent event ) { System.out.println( "收到事件通知:" + event.getState() +"\n" ); if (KeeperState.SyncConnected == event.getState() ) { latch.countDown(); } } public static void main(String[] args) throws Exception { NodeChangeTest test = new NodeChangeTest(); ZooKeeper zk = test.GetConnection(); zk.setData("/test", "zNode2".getBytes(), -1); zk.close(); } }
收到事件通知:SyncConnected
路径是:/test
如果是将网线断开,过了5s又插上将会有如下输出:
收到事件通知:SyncConnected
路径是:null
收到事件通知:Disconnected
路径是:null
收到事件通知:Expired
路径是:null
修改ZooKeeper节点的程序也没有任何反应。
ZooKeeper的“会话终止”是这么出现的