Zookeeper API基础

我的未来我决定 提交于 2020-03-09 11:56:43

环境搭建

第一步:创建一个Maven工程,添加Maven依赖:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.4</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.8.2</version>
</dependency>
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.13</version>
</dependency>
<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.11</version>
</dependency>

第二步:在resources目录下创建log4j.properties文件:

log4j.rootLogger=INFO, stdout  
log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n  
log4j.appender.logfile=org.apache.log4j.FileAppender  
log4j.appender.logfile.File=target/spring.log  
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n  

第三步:创建代码框架:

public class TestZK {
    private String connStr = "hcslave1:2181,hcmaster:2181,hcslave2:2181";
    private int sessionTimeout = 5000;
    private ZooKeeper zk = null;

    @Before
    public void init() throws IOException {
        //ip端口,连接超时时间,监听者
        zk = new ZooKeeper(connStr, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
		        if (event.getState() == Event.KeeperState.SyncConnected) {
   			         System.out.println("连接成功!");
                }
                // 收到事件通知后的回调函数(用户的业务逻辑)
                System.out.println(event.getType() + "--" + event.getPath());
            }
        });
    }
}

创建子节点

@Test
public void create() throws Exception {
    String res = zk.create("/aa/a1", "aaaa1111".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    System.out.println(res);
}
@Test
public void createEphemeral() throws Exception {
    String res = zk.create("/aa/a2", "aaaa2222".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    System.out.println(res);
}
解释:

public String create(String path, byte[] data, List acl, CreateMode createMode)
其中:

  • path:要创建的节点的路径
  • data:要存放的节点的数据
  • acl:节点权限,取值有:
    • OPEN_ACL_UNSAFE:公开,无需权限模式
    • CREATOR_ALL_ACL:创建者拥有全部的权限
    • READ_ACL_UNSAFE:只读模式
  • createMode:节点的类型/创建模式,取值有:
    • PERSISTENT:持久节点
    • PERSISTENT_SEQUENTIAL:持久节点并且顺序递增的
    • EPHEMERAL:临时节点
    • EPHEMERAL_SEQUENTIAL:临时节点,并且顺序递增的

设置节点数据

@Test
public void setData() throws Exception {
    zk.setData("/aa/a1", "hc".getBytes(), 0);
}
第三个参数是数据版本号。如果不需要确认当前数据版本,可传入版本号为-1。

判断节点是否存在

@Test
public void exist() throws Exception {
    Stat stat = zk.exists("/aa", false);
    System.out.println(stat == null ? "不存在" : "存在");
}

获取节点数据

@Test
public void getDate() throws KeeperException, InterruptedException {
    byte[] byteDate = zk.getData("/aa", null, null);
    System.out.println(new String(byteDate));
}

参数:节点,监听者,节点的状态信息stat如时间戳等

删除数据

@Test
public void delete() throws KeeperException, InterruptedException {
    zk.delete("/aa/a3", 1);//注意stat中的dataversion要一致,否则报错
}

若版本号传-1,则直接删除节点。

获取子节点

@Test
public void ls() throws Exception { 
    //参数:节点,监听者
    List<String> list = zk.getChildren("/", null);
    for (String s : list) {
        System.out.println(s);
    }
}

获取指定路径下的所有节点,包括子节点

@Test
public void lsAll() throws Exception {
    ls("/");
}
public void ls(String path) throws Exception {
    List<String> list = zk.getChildren(path, null);
    if (list == null || list.isEmpty()) {
        return;
    }
    for (String s : list) {
        if (path.equals("/")) {     //先输出孩子
            ls(path + s);
        } else {
            ls(path + "/" + s);
        }
    }
}

获取节点并监听节点变化

@Test
public void watchChange1() throws Exception {
    Stat stat = new Stat(); //状态
    byte[] data = zk.getData("/aa", new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            if (event.getType() == Event.EventType.NodeDataChanged) {
                System.out.println("节点数据改变了!");
            }
        }
    }, stat);
    System.out.println(new String(data));
    Thread.sleep(50000);
}

zookeeper中的监听默认是一次性的。要想永久监听需要自己处理:

@Test
public void watchChange2() throws Exception {
    Stat stat = new Stat(); //状态
    final String path = "/aa";
    byte[] data = zk.getData(path, new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            if (event.getType() == Event.EventType.NodeDataChanged) {
                try {
                    byte[] res = zk.getData(path, this, stat);//设置可以反复监听
                    System.out.println("节点数据改变了 " + new String(res));
                } catch (KeeperException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }, stat);
    System.out.println(new String(data));
    Thread.sleep(50000);
}

获取节点并监听节点删除

@Test
public void watchDelete() throws Exception {
    String path = "/aa/a2";
    Stat stat = new Stat(); //状态

    byte[] data = zk.getData(path, new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            if (event.getType() == Event.EventType.NodeDeleted) {
                System.out.println("节点数据删除了!");
            }
        }
    }, stat);

    System.out.println("****" + new String(data));

    // 延时阻塞
    Thread.sleep(Long.MAX_VALUE);
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!