使用Java操作Zookeeper

目录

一、介绍

二、zookeeper API

  2.1、导入依赖

  2.2、连接zk集群

  2.3、操作数据操作

三、zkClient API

  3.1、导入依赖

  3.2、使用示例

 

 

 

 

一、介绍

  这里主要记录通过Java调用API来操作Zookeeper集群的数据,对于zookeeper集群的搭建或者命令,可以参考:

  目前接触到的Java操作Zookeeper,有两套API,一套是zookeeper官方提供的(zookeeper),另外一套是封装了官方API的API(zkClient),从描述上来看,就知道,官方的API可能不是那么好用,不然也不会在封装。  

 

二、zookeeper API

2.1、导入依赖

  使用zookeeper官方api的时候,请保证jar包的版本,和zk集群中zk的版本相同

<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.7</version>
</dependency>

  

2.2、连接zk集群

  下面是代码示例,两种形式(分别使用匿名类和Lambda表达式):

package cn.ganlixin.zk;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.junit.Test;

import java.io.IOException;

public class ZookeeperDemo {

    @Test
    public void connectZkCluster() throws IOException, KeeperException, InterruptedException {

        // 构造方法
        // ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
        
        // 匿名对象形式
        ZooKeeper zooKeeper = new ZooKeeper(
                "192.168.1.3:2181,192.168.1.4:2181,192.168.1.5:2181",
                20000,
                new Watcher() {
                    @Override
                    public void process(WatchedEvent watchedEvent) {
                        // 发生变更的节点路径
                        String path = watchedEvent.getPath();
                        System.out.println("path:" + path);

                        // 通知状态
                        Watcher.Event.KeeperState state = watchedEvent.getState();
                        System.out.println("KeeperState:" + state);

                        // 事件类型
                        Watcher.Event.EventType type = watchedEvent.getType();
                        System.out.println("EventType:" + type);
                    }
                }
        );

        // 关闭连接
        zooKeeper.close();

        // Lamdba形式
        ZooKeeper zk = new ZooKeeper(
                "192.168.1.3:2181,192.168.1.4:2181,192.168.1.5:2181",
                20000,
                watchedEvent -> {
                    // 发生变更的节点路径
                    String path = watchedEvent.getPath();
                    System.out.println("path:" + path);

                    // 通知状态
                    Watcher.Event.KeeperState state = watchedEvent.getState();
                    System.out.println("KeeperState:" + state);

                    // 事件类型
                    Watcher.Event.EventType type = watchedEvent.getType();
                    System.out.println("EventType:" + type);
                }
        );

        zk.close();
    }
}

  

  运行上面的代码,控制台输出如下(输出了两遍,是因为创建了两次连接)

path:null
KeeperState:SyncConnected
EventType:None
path:null
KeeperState:SyncConnected
EventType:None

  

2.3、操作数据操作

  操作Zk中的数据,方式也很简单,只需要使用创建的zk连接,调用对应的方法即可(方法名与zk命令行中命令相同)

package cn.ganlixin.zk;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;

import java.io.IOException;

public class ZookeeperDemo {

    @Test
    public void manageData() throws KeeperException, InterruptedException, IOException {

        // 创建zk连接
        ZooKeeper zk = new ZooKeeper(
                "192.168.1.3:2181,192.168.1.4:2181,192.168.1.5:2181",
                20000,
                null
        );

        // 创建节点
        zk.create("/abc", "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        // 获取节点数据
        // getData(String path, boolean watch, Stat stat);
        Stat stat = new Stat();
        byte[] data = zk.getData("/abc", false, stat);
        System.out.println(new String(data));       // 数据内容 123
        System.out.println(stat.getDataLength());   // 节点状态(数据长度) 3

        // 对/abc进行watch
        zk.getData("/abc",
                watchedEvent -> {
                    System.out.println("path:" + watchedEvent.getPath());
                    System.out.println("KeeperState:" + watchedEvent.getState());
                    System.out.println("EventType:" + watchedEvent.getType());
                },
                null);

        // 设置节点数据
        // setData(String path, byte[] data, int version)
        // 指定version为-1,表示不关心版本
        zk.setData("/abc", "456".getBytes(), -1);

        // 设置两次,第二次不会触发通知
        zk.setData("/abc", "789".getBytes(), -1);

        // 阻塞,以等待通知
        Thread.sleep(1000);
        zk.close();
    }
}

  上面的程序,运行输出结果如下:

123
3
path:/abc
KeeperState:SyncConnected
EventType:NodeDataChanged  

  可以看到,只显示了一次通知,和与预期相符。

 

三、zkClient API

  因为Zookeeper API比较复杂,使用并不方便,所以出现了ZkClient,ZkClient对Zookeeper API进行了封装,利用ZkClient可以更加方便地对Zookeeper进行操作。

3.1、导入依赖

  因为zkClient是对zookeeper的再封装,所以需要注意zkClient中zookeeper的版本与zk集群的版本相同,可以在maven仓库中查看对应关系

<!-- https://mvnrepository.com/artifact/com.101tec/zkclient -->
<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.10</version>
</dependency>

  

3.2、使用示例

  下面是个简单的示例:

package cn.ganlixin.zk;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkStateListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.Watcher;
import org.junit.Test;

import java.util.List;

public class ZkClientDemo {

    @Test
    public void testConn() throws InterruptedException {
        ZkClient zkClient = new ZkClient(
                "192.168.1.3:2181,192.168.1.4:2181,192.168.1.5:2181",
                20000
        );

        // 创建节点
        zkClient.createPersistent("/abc", "hello");
        zkClient.createEphemeral("/xyz", "world");
        zkClient.create("/opq", "world", CreateMode.EPHEMERAL_SEQUENTIAL);

        String data = zkClient.readData("/abc");
        System.out.println(data);

        // 监听状态变化
        zkClient.subscribeStateChanges(new IZkStateListener() {
            @Override
            public void handleStateChanged(Watcher.Event.KeeperState keeperState) throws Exception {
                System.out.println("state:" + keeperState);
            }

            @Override
            public void handleNewSession() throws Exception {
                System.out.println("new session");
            }

            @Override
            public void handleSessionEstablishmentError(Throwable throwable) throws Exception {
                throwable.printStackTrace();
            }
        });

        // 监听子节点发生变化
        zkClient.subscribeChildChanges("/", new IZkChildListener() {
            @Override
            public void handleChildChange(String path, List<String> list) throws Exception {
                System.out.println("watch path:" + path);
                // 输出所有子节点
                list.forEach(str -> {
                    System.out.println(str);
                });
            }
        });

        Thread.sleep(100000);
    }
}

  

  

 

 

posted @ 2019-06-09 16:33  寻觅beyond  阅读(...)  评论(...编辑  收藏
顶部