zookeeper java api(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GoSaint/article/details/83750237

1 Zookeeper安装以及启动

    这里我已经进行了安装,并且启动了Zookeeper。端口是2182

2 Zookeeper config

tickTime=2000

initLimit=10

syncLimit=5

dataDir=D://zookiper/zookeeper/data

clientPort=2182

    参数介绍

tickTime:  这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。

dataDir:    顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。

clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。

initLimit:   这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器 群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10 个心跳的时间(也就是tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒

syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒

连接zk服务器

    依赖的pom

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.5.3-beta</version>
            <type>pom</type>
        </dependency>
    public static ZooKeeper zkClient(){
        
        final String connectString="127.0.0.1:2182";
        final int sessionTimeout=5000;
        ZooKeeper zooKeeper=null;
        try {
             zooKeeper=new ZooKeeper(connectString, sessionTimeout, new Watcher() {
                @Override
                public void process(final WatchedEvent event) {
                    /** 判断是否和服务器之间取得了连接*/
                    if(event.getState()==Event.KeeperState.SyncConnected){
                        System.out.println("已经触发了" + event.getType() + "事件!");
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return zooKeeper;
    }

    在上述中,connectString,sessionTimeout表示连接服务器的地址,以及客户端连接服务器端的session超时时间。watcher为监视器。zookeeper api和服务器之间的连接是异步的。当执行 ZooKeeper zooKeeper = new ZooKeeper("127.0.0.1:2181", 5000, watcher) 这句代码之后,会立马返回zkclient;当与服务器建立好连接之后会 ,调用Watcher中的process方法进行处理。 process方法会接受一个WatchedEvent类型的参数,用于表明发生了什么事件。

    下属代码块可以作为连接zk的模板。

public void process(WatchedEvent watchedEvent) {
    if (watchedEvent.getState() == Event.KeeperState.SyncConnected) { //判断是否已连接
        if(watchedEvent.getType() == Event.EventType.None && null == watchedEvent.getPath()) {
            // 最初与zk服务器建立好连接
        } else if(watchedEvent.getType() == Event.EventType.NodeChildrenChanged) {
            // 子节点变化事件
        }
        // ...还可以继续监听其它事件类型
    }
    System.out.println(watchedEvent.getState());
}

WatchedEvent包含两方面重要信息:

    1 与zk服务器连接的状态信息

    可以调用watchedEvent.getState()方法获取与zk服务器连接的状态信息,状态信息取值主要包括SyncConnectedDisconnectedConnectedReadOnlyAuthFailed等等。

    2 发生的具体事件类型信息
watchedEvent.getState()方法只是获取与zk服务器连接的状态信息,但在同一个连接状态下,还会发生很多事件的类型。例如在zk中,我们可以watch一个节点的数据内容,当这个节点的数据被改变时,我们可以获取到这个事件。类似的还有子节点列表变化事件等等。这就需要我们在SyncConnected同一种连接状态下区分多个事件类型。可以通过watchedEvent.getType()方法获取具体的事件类型。

    事件类型的取值包括NoneNodeCreatedNodeDeletedNodeDataChangedNodeChildrenChanged

4 创建节点

    下面要介绍的每种api操作都可以分为两种类型——同步和异步。同步操作一般会有返回值,并且会抛出相应的异常。异步操作没有返回值,也不会抛出异常。此外异步方法参数在同步方法参数的基础上,会增加Callback和context两个参数。如用同步方式创建一个节点的的代码如下:

  •     创建同步节点
public static void createNodeSync() throws KeeperException, InterruptedException {
        String path = "/poype_node";
        ZooKeeper zooKeeper = zkClient();
        String nodePath = zooKeeper.create(path, "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println(nodePath);
}

看ZkClient创建节点完毕:

关于上述的GUI工具,可以参见这篇文章:https://www.cnblogs.com/easyworld/p/8463910.html

同步下创建节点的方法create(*)介绍

public String create(final String path, byte data[], 
                           List<ACL> acl,CreateMode createMode) 
                    throws KeeperException, InterruptedException

参数介绍:

  • path:创建节点的路径
  • data[] : 创建节点的数据值,参数类型是字节数组
  • acl:节点的访问权限,我们这里指定该节点可以被任何人访问

createMode:create命令可以有-s和-e两个参数,其中-s是顺序节点,-e是临时节点。这里的CreateMode就是这两个参数的组合。可选的值:

PERSISTENT
永久节点
PERSISTENT_SEQUENTIAL
永久有序节点
EPHEMERAL
临时节点
EPHEMERAL_SEQUENTIAL
临时有序节点
  •     创建异步节点

    异步模式方法没有返回值,并且不会抛出任何异常:除了同步create方法中的四个参数以外,异步模式的create方法还增加了callback和context两个参数。StringCallback接口中的processResult方法会在节点创建好之后被调用,它有四个参数。第一个是int类型的resultCode,作为创建节点的结果码,当成功创建节点时,resultCode的值为0。第二个参数是创建节点的路径。第三个参数是context,当一个StringCallback类型对象作为多个create方法的参数时,这个参数就很有用了。第四个参数是创建节点的名字,其实与path参数相同。

    在我用其中的一种方式,怎么也创建不了节点,就是如下的代码:

 public static ZooKeeper zkClient(){
        /** connectString  ZK连接地址
         *  sessionTimeout 回话超时时间 单位ms
         *  ************************************************
         *  watcher        监视器
         *  关于监视器:zookeeper api与服务器建立连接的过程是异步的。
         *  ZooKeeper zooKeeper = new ZooKeeper("127.0.0.1:2181", 5000, watcher);
         *  上面的调用会马上从ZooKeeper构造函数返回,当与服务器建立好连接之后会
         *      调用Watcher中的process方法进行处理。
         *  process方法会接受一个WatchedEvent类型的参数,用于表明发生了什么事件。*/
        final String connectString="127.0.0.1:2182";
        final int sessionTimeout=5000;
        ZooKeeper zooKeeper=null;
        try {
             zooKeeper=new ZooKeeper(connectString, sessionTimeout, new Watcher() {
                @Override
                public void process(final WatchedEvent watchedEvent) {
                    /** 判断是否和服务器之间取得了连接*/
                    if(watchedEvent.getState()==Event.KeeperState.SyncConnected){
                        System.out.println("已经触发了" + watchedEvent.getType() + "事件!");
                    }
                }
            });

        } catch (IOException e) {
            e.printStackTrace();
        }
        return zooKeeper;
    }
private static void createNodeAsync() {
        String path = "/poype_node2";
        ZooKeeper zooKeeper = zkClient();
        zooKeeper.create(path, "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT,
                new MyStringCallBack(), "create");
    }
    static class MyStringCallBack implements AsyncCallback.StringCallback{
        @Override
        public void processResult(final int rc, final String path, final Object ctx, final String name) {
            System.out.println("异步创建回调结果:状态:" + rc +";创建路径:" +
                    path + ";传递信息:" + ctx + ";实际节点名称:" + name);
        }
    }

最后采用另外一种方式创建了节点:

  • 同步方式获取节点数据
public class CreateNode implements Watcher {

    private static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {
        ZooKeeper zooKeeper = new ZooKeeper("127.0.0.1:2182", 5000, new CreateNode());
        countDownLatch.await();
        /** 异步创建临时节点*/
        zooKeeper.create("/poype_node2", "abc".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, new MyStringCallBack(), "我是传递内容");
        /**  验证等待回调结果使用,可根据实际情况自行调整*/
        Thread.sleep(10000);
    }

    @Override
    public void process(WatchedEvent event) {
        if (Event.KeeperState.SyncConnected == event.getState()) {
            countDownLatch.countDown();
        }
    }
    static class MyStringCallBack implements AsyncCallback.StringCallback {
        @Override
        public void processResult(int rc, String path, Object ctx, String name) {
            System.out.println("异步创建回调结果:状态:" + rc +";创建路径:" +
                    path + ";传递信息:" + ctx + ";实际节点名称:" + name);
        }
    }
}

zooKeeper.getData方法的返回值就是节点中存储的数据值,它有三个参数,第一个参数是节点的路径,用于表示要获取哪个节点中的数据。第三个参数stat用于存储节点的状态信息,在调用getData方法前,会先构造一个空的Stat类型对象作为参数传给getData方法,当getData方法调用返回后,节点的状态信息会被填充到stat对象中。
第二个参数是一个bool类型的watch,这个参数比较重要。当watch为true时,表示我们想要监控这个节点的数据变化。当节点的数据发生变化时,我们就可以拿到zk服务器推送给我们的通知。在process方法中会有类似下面的代码:

public void process(WatchedEvent watchedEvent) {
    if (watchedEvent.getState() == Event.KeeperState.SyncConnected) { //与zk服务器处于连接状态
        if(watchedEvent.getType() == Event.EventType.None && null == watchedEvent.getPath()) {
            createNodeAsync();
        } else if(watchedEvent.getType() == Event.EventType.NodeChildrenChanged) {
            // 节点的子节点列表发生变化
        } else if(watchedEvent.getType() == Event.EventType.NodeDataChanged) {
            // 节点的数据内容发生变化
        }
    }
}

当节点的数据内容发生变化时,我们就会接收到NodeDataChanged这个事件。值得注意的是,zooKeeper设置的监听只生效一次,如果在接收到NodeDataChanged事件后还想继续对该节点的数据内容改变进行监听,需要在事件处理逻辑中重新调用getData方法并将watch参数设置为true。
异步获取一个节点数据值的代码如下:

  • 异步方式获取节点数据
ublic class CreateNode implements Watcher {

    private static CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {
        ZooKeeper zooKeeper = new ZooKeeper("127.0.0.1:2182", 5000, new CreateNode());
        countDownLatch.await();
    
        zooKeeper.getData("/poype_node2",true,new MyStringCallBackData(),"异步获取节点的数据值");
        Thread.sleep(10000);

    }

    @Override
    public void process(WatchedEvent event) {
        if (Event.KeeperState.SyncConnected == event.getState()) {
            countDownLatch.countDown();
        }
    }
   
    static class MyStringCallBackData implements AsyncCallback.DataCallback{

        @Override
        public void processResult(final int rc, final String path, final Object ctx,
                final byte[] data, final Stat stat) {
            System.out.println(rc);
            System.out.println(path);
            System.out.println(ctx);
            System.out.println("***********");
            System.out.println(new String(data));
            System.out.println(stat);
        }
    }
}

参考:https://segmentfault.com/a/1190000012262940

        :  https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/index.html

        :  https://www.cnblogs.com/easyworld/p/8463910.html

        :https://blog.csdn.net/wo541075754/article/details/65625481

猜你喜欢

转载自blog.csdn.net/GoSaint/article/details/83750237