zookeeper学习记录-06 Zookeeper JavaAPI操作

新建一个maven项目

引入依赖jar包

pom.xml引入依赖jar包,实际上还需要sla4j和log4j,但是maven会自动帮忙我们引入这里只需要引入Zookeeper的即可

<dependency>
      <groupId>org.apache.zookeeper</groupId>
      <artifactId>zookeeper</artifactId>
      <version>3.4.6</version>
</dependency>

新建一个类 - 测试连接Zookeeper服务器

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample implements Watcher{

    private static CountDownLatch connCountDownLatch = new CountDownLatch(1);

    @Override
    public void process(WatchedEvent event) {
        System.out.println("Receive watched event : " + event);
        if(KeeperState.SyncConnected == event.getState()){
            connCountDownLatch.countDown();
        }
    }

    public static void main(String[] args) {

        try {
            ZooKeeper zooKeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample());
            System.out.println(zooKeeper.getState());
            connCountDownLatch.await();
            System.out.println("Zookeeper session established");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这里定义一个CountDownLatch ,在main方法中处于等待状态,当Zookeeper客户端连接上服务器之后解除阻塞,最终输出结果

CONNECTING
Receive watched event : WatchedEvent state:SyncConnected type:None path:null
Zookeeper session established

Zookeeper构造说明:

这里写图片描述

在Zookeeper客户端与服务端建立连接是一个异步的过程,也就是说代码Zookeeper实例化之后马上返回,并没有真正的连接上了服务器端,所以代码中加上了CountDownLatch 来进行阻塞,当连接成功之后解除阻塞,打印最后一段话

创建节点

创建节点中两种方式,同步、异步.
参数说明:
这里写图片描述

同步

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample_Create_API_Sync implements Watcher{

    private static CountDownLatch connCountDownLatch = new CountDownLatch(1);

    @Override
    public void process(WatchedEvent event) {
        System.out.println("Receive watched event : " + event);
        if(KeeperState.SyncConnected == event.getState()){
            connCountDownLatch.countDown();
        }
    }

    public static void main(String[] args) throws Exception {
        ZooKeeper zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Create_API_Sync());
        System.out.println(zookeeper.getState());
        connCountDownLatch.await();

        String path1 = zookeeper.create("/zk-test-PERSISTENT-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);    
        System.out.println("Success create znode: " + path1);
    }

}

输出结果如下:可以看到

CONNECTING
Receive watched event : WatchedEvent state:SyncConnected type:None path:null
Success create znode: /zk-test-PERSISTENT-

异步

异步方式于同步方式的区别在于节点的创建过程(包括网络通信和服务端的节点创建过程)是异步的,在同步接口调用过程中,开发者需要关注接口抛出异常的可能,但是在异步接口中,接口本身不会抛出异常,所有异常都会在回调函数中通过Result Code来体现。

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample_Create_API_ASync implements Watcher{

    private static CountDownLatch connCountDownLatch = new CountDownLatch(1);

    @Override
    public void process(WatchedEvent event) {
        System.out.println("Receive watched event : " + event);
        if(KeeperState.SyncConnected == event.getState()){
            connCountDownLatch.countDown();
        }
    }

    public static void main(String[] args) throws Exception {
        ZooKeeper zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Create_API_ASync());
        System.out.println(zookeeper.getState());
        connCountDownLatch.await();


        zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,
                new IStringCallback(), "I am context. ");

        Thread.sleep(Integer.MAX_VALUE);
    }


    static class IStringCallback implements AsyncCallback.StringCallback{

        @Override
        public void processResult(int rc, String path, Object ctx, String name) {
            System.out.println("Create path result: [" + rc + ", " + path + ", " + ctx + ", real path name: " + name);
        }
    }
}

输出结果如下:

CONNECTING
Receive watched event : WatchedEvent state:SyncConnected type:None path:null
Create path result: [-110, /zk-test-ephemeral-, I am context. , real path name: null

异步回调参数说明:
这里写图片描述

删除节点

删除节点提供了两个方法,分别是同步和异步.
这里写图片描述

参数说明:
这里写图片描述

同步

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample_DELETE_API_Sync implements Watcher{

    private static CountDownLatch connCountDownLatch = new CountDownLatch(1);

    @Override
    public void process(WatchedEvent event) {
        System.out.println("Receive watched event : " + event);
        if(KeeperState.SyncConnected == event.getState()){
            connCountDownLatch.countDown();
        }
    }

    public static void main(String[] args) throws Exception {
        ZooKeeper zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_DELETE_API_Sync());
        System.out.println(zookeeper.getState());
        connCountDownLatch.await();

        zookeeper.delete("/zk-test-ephemeral-", 0);

    }

}

异步

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample_DELETE_API_ASync implements Watcher{

    private static CountDownLatch connCountDownLatch = new CountDownLatch(1);

    @Override
    public void process(WatchedEvent event) {
        System.out.println("Receive watched event : " + event);
        if(KeeperState.SyncConnected == event.getState()){
            connCountDownLatch.countDown();
        }
    }

    public static void main(String[] args) throws Exception {
        ZooKeeper zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_DELETE_API_ASync());
        System.out.println(zookeeper.getState());
        connCountDownLatch.await();

        zookeeper.create("/zk123", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        zookeeper.delete("/zk123", 0 , new IVoidCallBack() , "test-delete async");

        Thread.sleep(Integer.MAX_VALUE);
    }

    static class IVoidCallBack implements AsyncCallback.VoidCallback{

        @Override
        public void processResult(int rc, String path, Object ctx) {
            System.out.println("rc : " + rc + " , path : " + path + " ctx : " + ctx.toString());
        }

    }
}

输出如下:

CONNECTING
Receive watched event : WatchedEvent state:SyncConnected type:None path:null
rc : 0 , path : /zk123 ctx : test-delete async

子节点读取

这里写图片描述

参数说明

这里写图片描述
这里写图片描述

同步

import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample_Children_API_Sync implements Watcher{

    private static CountDownLatch connCountDownLatch = new CountDownLatch(1);

    private static ZooKeeper zookeeper = null;

    private static String path = "/zk01";

    @Override
    public void process(WatchedEvent event) {
        System.out.println("Receive watched event : " + event);
        if(KeeperState.SyncConnected == event.getState()){
            if(event.getType() == EventType.None && null == event.getPath()){
                connCountDownLatch.countDown();
            }else if(event.getType() == EventType.NodeChildrenChanged){
                try {
                    System.out.println("child change  reget childs : " + zookeeper.getChildren(path, true));
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Children_API_Sync());
        System.out.println(zookeeper.getState());
        connCountDownLatch.await();


        zookeeper.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zookeeper.create(path + "/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        List<String> childs = zookeeper.getChildren(path, true);
        System.out.println(childs);

        zookeeper.create(path + "/c2", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        Thread.sleep(Integer.MAX_VALUE);
    }
}

输出结果:

CONNECTING
Receive watched event : WatchedEvent state:SyncConnected type:None path:null
[c1]
Receive watched event : WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/zk01
child change  reget childs : [c1, c2]

需要注意的是Watcher通知是一次性的,即一旦触发一次通知后,该Watcher就失效了,因此客户端需要反复注册Watcher,即程序中在process里面又注册了Watcher

异步

import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class ZK_Sample_Children_API_ASync implements Watcher{

    private static CountDownLatch connCountDownLatch = new CountDownLatch(1);

    private static ZooKeeper zookeeper = null;

    private static String path = "/zk02";

    @Override
    public void process(WatchedEvent event) {
        System.out.println("Receive watched event : " + event);
        if(KeeperState.SyncConnected == event.getState()){
            if(event.getType() == EventType.None && null == event.getPath()){
                connCountDownLatch.countDown();
            }else if(event.getType() == EventType.NodeChildrenChanged){
                try {
                    System.out.println("child change  reget childs : " + zookeeper.getChildren(path, true));
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        zookeeper = new ZooKeeper("192.168.7.151:2181", 5000, new ZK_Sample_Children_API_ASync());
        System.out.println(zookeeper.getState());
        connCountDownLatch.await();


        zookeeper.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zookeeper.create(path + "/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        zookeeper.getChildren(path, true,new IChildren2Callback(),"获取子节点");

        zookeeper.create(path + "/c2", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        Thread.sleep(Integer.MAX_VALUE);
    }

    static class IChildren2Callback implements AsyncCallback.Children2Callback {
        public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
            System.out.println("Get Children znode result: [response code: " + rc + ", path: " + path + ", ctx: "
                    + ctx + ", children list: " + children + ", stat: " + stat);
        }
    }
}

数据获取

Zookeeper API 提供了四个接口来获取数据,同样分同步,异步.

这里写图片描述

参数说明
这里写图片描述

更新数据

Zookeeper API 提供了两个接口来更新数据,同样分同步,异步.

这里写图片描述

参数说明
这里写图片描述

在更新数据时,setData方法存在一个version参数,其用于指定节点的数据版本,表明本次更新操作是针对指定的数据版本进行的,但是,在getData方法中,并没有提供根据指定数据版本来获取数据的接口,那么,这里为何要指定数据更新版本呢,这里方便理解,可以等效于CAS(compare and swap),对于值V,每次更新之前都会比较其值是否是预期值A,只有符合预期,才会将V原子化地更新到新值B。Zookeeper的setData接口中的version参数可以对应预期值,表明是针对哪个数据版本进行更新,假如一个客户端试图进行更新操作,它会携带上次获取到的version值进行更新,而如果这段时间内,Zookeeper服务器上该节点的数据已经被其他客户端更新,那么其数据版本也会相应更新,而客户端携带的version将无法匹配,无法更新成功,因此可以有效地避免分布式更新的并发问题。

检测节点是否存在

Zookeeper API 提供了四个接口来检测节点是否存在,同样分同步,异步.

这里写图片描述

参数说明

这里写图片描述

在调用接口时注册Watcher的话,还可以对节点是否存在进行监听,一旦节点被创建、被删除、数据更新,都会通知客户端

同步

import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample_Exist_API_Sync implements Watcher {
    private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
    private static ZooKeeper zk;

    public static void main(String[] args) throws Exception {
        String path = "/zk-book";
        zk = new ZooKeeper("192.168.7.151:2181", 5000, //
                new ZK_Sample_Exist_API_Sync());
        connectedSemaphore.await();

        zk.exists(path, true);

        zk.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zk.setData(path, "123".getBytes(), -1);

        zk.create(path + "/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("success create znode: " + path + "/c1");

        zk.delete(path + "/c1", -1);
        zk.delete(path, -1);

        Thread.sleep(Integer.MAX_VALUE);
    }

    public void process(WatchedEvent event) {
        try {
            if (KeeperState.SyncConnected == event.getState()) {
                if (EventType.None == event.getType() && null == event.getPath()) {
                    connectedSemaphore.countDown();
                } else if (EventType.NodeCreated == event.getType()) {
                    System.out.println("success create znode: " + event.getPath());
                    zk.exists(event.getPath(), true);
                } else if (EventType.NodeDeleted == event.getType()) {
                    System.out.println("success delete znode: " + event.getPath());
                    zk.exists(event.getPath(), true);
                } else if (EventType.NodeDataChanged == event.getType()) {
                    System.out.println("data changed of znode: " + event.getPath());
                    zk.exists(event.getPath(), true);
                }
            }
        } catch (Exception e) {
        }
    }
}

输出结果

success create znode: /zk-book
data changed of znode: /zk-book
success create znode: /zk-book/c1
success delete znode: /zk-book
  • 无论节点是否存在,都可以通过exists接口注册Watcher。

  • 注册的Watcher,对节点创建、删除、数据更新事件进行监听。

  • 对于指定节点的子节点的各种变化,不会通知客户端。

异步

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class ZK_Sample_Exist_API_ASync implements Watcher {
    private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
    private static ZooKeeper zk;

    public static void main(String[] args) throws Exception {
        String path = "/zk-book";
        zk = new ZooKeeper("192.168.7.151:2181", 5000,
                new ZK_Sample_Exist_API_ASync());
        connectedSemaphore.await();

        zk.exists(path, true, new IIStatCallback(), null);

        zk.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE,
                CreateMode.PERSISTENT);
        zk.setData(path, "123".getBytes(), -1);

        zk.create(path + "/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE,
                CreateMode.PERSISTENT);
        System.out.println("success create znode: " + path + "/c1");

        zk.delete(path + "/c1", -1);
        zk.delete(path, -1);

        Thread.sleep(Integer.MAX_VALUE);
    }

    public void process(WatchedEvent event) {
        try {
            if (KeeperState.SyncConnected == event.getState()) {
                if (EventType.None == event.getType()
                        && null == event.getPath()) {
                    connectedSemaphore.countDown();
                } else if (EventType.NodeCreated == event.getType()) {
                    System.out.println("success create znode: "
                            + event.getPath());
                    zk.exists(event.getPath(), true, new IIStatCallback(), null);
                } else if (EventType.NodeDeleted == event.getType()) {
                    System.out.println("success delete znode: "
                            + event.getPath());
                    zk.exists(event.getPath(), true, new IIStatCallback(), null);
                } else if (EventType.NodeDataChanged == event.getType()) {
                    System.out.println("data changed of znode: "
                            + event.getPath());
                    zk.exists(event.getPath(), true, new IIStatCallback(), null);
                }
            }
        } catch (Exception e) {
        }
    }

    static class IIStatCallback implements AsyncCallback.StatCallback {
        public void processResult(int rc, String path, Object ctx, Stat stat) {
            System.out.println("rc: " + rc + ", path: " + path + ", stat: " + stat);
        }
    }
}

输出结果

rc: -101, path: /zk-book, stat: null
success create znode: /zk-book
rc: 0, path: /zk-book, stat: 12884901993,12884901993,1508491896292,1508491896292,0,0,0,0,0,0,12884901993

data changed of znode: /zk-book
rc: 0, path: /zk-book, stat: 12884901993,12884901994,1508491896292,1508491896313,1,0,0,0,3,0,12884901993

success create znode: /zk-book/c1
success delete znode: /zk-book
rc: -101, path: /zk-book, stat: null

当节点不存在时,其rc(ResultCode)为-101。

权限认证

在实际过程中,可能是一个Zookeeper集群,有多个项目,多个服务共同使用,避免错误操作,数据读取权限,就需要进行认证了。
Zookeeper api 提供了权限认证
这里写图片描述

参数说明:

这里写图片描述

认证失败示例

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample_ACL_API_AUTH_FAIL{

    public static void main(String[] args) throws Exception {

        String path = "/zk-book";
        ZooKeeper zookeeper1 = new ZooKeeper("192.168.7.151:2181", 5000, null);
        zookeeper1.addAuthInfo("digest", "foo:true".getBytes());
        zookeeper1.create(path, "init".getBytes(), Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL);
        System.out.println("success create znode: " + path);
        ZooKeeper zookeeper2 = new ZooKeeper("192.168.7.151:2181", 5000, null);
        zookeeper2.getData(path, false, null);
    }

}

输出结果

success create znode: /zk-book
Exception in thread "main" org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /zk-book
    at org.apache.zookeeper.KeeperException.create(KeeperException.java:113)
    at org.apache.zookeeper.KeeperException.create(KeeperException.java:51)
    at org.apache.zookeeper.ZooKeeper.getData(ZooKeeper.java:1155)
    at org.apache.zookeeper.ZooKeeper.getData(ZooKeeper.java:1184)
    at com.jx.zk.first.ZK_Sample_ACL_API_AUTH_FAIL.main(ZK_Sample_ACL_API_AUTH_FAIL.java:16)

认证通过

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;

public class ZK_Sample_ACL_API_AUTH_SUCC{

    public static void main(String[] args) throws Exception {

        String path = "/zk-book";
        ZooKeeper zookeeper1 = new ZooKeeper("192.168.7.151:2181", 5000, null);
        zookeeper1.addAuthInfo("digest", "foo:true".getBytes());
        zookeeper1.create(path, "init".getBytes(), Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL);
        System.out.println("success create znode: " + path);
        ZooKeeper zookeeper2 = new ZooKeeper("192.168.7.151:2181", 5000, null);

        zookeeper2.addAuthInfo("digest", "foo:true".getBytes());
        byte[] bt = zookeeper2.getData(path, false, null);
        System.out.println(new String(bt));
    }

}

输出结果

success create znode: /zk-book
init

不同的客户端之间带上一样的认证信息即可.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值