zookeeper断线重连无鉴权

问题:

 原理:

      ZooKeeper的watcher是一次性的,也就是说,每次在处理完状态变化事件之后,需要重新注册watcher,这一特性也使得在处理事件和重新加上watcher这段时间发生的节点状态变化将无法被感知。
       还有两个细节问题也需要注意,Zookeeper常常发生下面两种系统异常:
       org.apache.ZooKeeper.KeeperException.ConnectionLossException,客户端与其中的一台服务器socket连接出现异常,连接丢失;
       org.apache.ZooKeeper.KeeperException.SessionExpiredException,客户端的session已经超过sessionTimeout,未进行任何操作。
       ConnectionLossException异常可以通过重试进行处理,客户端会根据初始化ZooKeeper时传递的服务列表,自动尝试下一个服务端节点,而在这段时间内,服务器节点变更的事件就会丢失。
       SessionExpiredExecption异常不能通过重试进行解决,需要应用重新创建一个新的客户端,这时所有的watcher和EPHEMERAL节点都将失效。

       ZooKeeper的第三方客户端工具包zkClient(com.101tec:zkclient:0.8)解决了watcher的一次性注册问题,将znode的事件重新定义为子节点的变化、数据的变化、连接及状态的变化三类,由zkClient统一将watcher的WatchedEvent转换到以上三种情况中去处理,watcher执行后重新读取数据同时,再注册相同的watcher。zkClient在发生session expire异常时会自动创建新的ZooKeeper实例进行重连。当然,这时原来所有的watcher和EPHEMERAL节点都将失效,可以在zkClient定义的连接状态变化的接口IzkStateListener里面的handleNewSession方法中进行相应的处理。同时,zkClient还提供了ZKSerializer接口,可进行序列化和反序列化的相关操作,简化了znode的数据存储。
       zkClient将Zookeeper的watcher机制转换为一种更加容易理解的订阅形式,并且这种关系是可以保持的,而非一次性的。也就是说,当watcher使用完后,zkClient会自动再增加一个相同的watcher。节点有三种状态可供订阅,一类是子节点的变化,一类是数据变化,还有一类是状态的变化。

ZkClient zkClient = new ZkClient(serverList);
//创建节点
zkClient.createPersistent(PATH);
//创建子节点
zkClient.create(PATH+"/child","child znode", CreateMode.EPHEMERAL);
//获得子节点
List<String> children = zkClient.getChildren(PATH);
//获得子节点个数
int childCount = zkClient.countChildren(PATH);
//判断节点是否存在
zkClient.exists(PATH);
//写入数据
zkClient.writeData(PATH+"/chil", "hello world");
//读取节点数据
Object obj = zkClient.readData(PATH+"/child");
//删除节点
zkClient.delete(PATH+"/child");



//订阅子节点的变化
zkClient.subscribeChildChanges(PATH, new IZkChildListener() {
    @Override
    public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
    }
});

//订阅节点数据变化
zkClient.subscribeDataChanges(PATH, new IZkDataListener() {
    @Override
    public void handleDataChange(String dataPath, Object data) throws Exception {

    }

    @Override
    public void handleDataDeleted(String dataPath) throws Exception {

    }
});


//订阅连接状态的变化
zkClient.subscribeStateChanges(new IZkStateListener(){
    @Override
    public void handleStateChanged(Watcher.Event.KeeperState state) throws Exception {

    }

    @Override
    public void handleNewSession() throws Exception {

    }

    @Override
    public void handleSessionEstablishmentError(Throwable error) throws Exception {

    }
});

解决方法:

session过期后会生成一个新的session, 在生成新session之后赋权就可以了。

 


版权声明:本文为a18827547638原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>