ZooKeeper常用API的基本使用

针对ZooKeeper的会话创建,节点创建、删除,数据读取、更新,权限控制等API进行简单的验证。

1、新建一个maven工程,添加以下依赖

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

2、新建单元测试进行验证

/**
 * 软件版权:流沙~~
 * 修改日期   修改人员     修改说明
 * =========  ===========  =====================
 * 2020/1/14    liusha   新增
 * =========  ===========  =====================
 */
package com.sand.zookeeper;

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.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;

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

/**
 * 功能说明:ZooKeeper Api 测试类
 * 开发人员:@author liusha
 * 开发日期:2020/1/14 9:58
 * 功能描述:会话创建,节点创建、删除,数据读取、更新,权限控制等
 */
public class ZooKeeperApi implements Watcher {
  private static ZooKeeper zooKeeper = null;
  private static final String host = "127.0.0.1:2181";
  private static CountDownLatch countDownLatch = new CountDownLatch(1);
  private static final String hosts = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183";

  /**
   * ZooKeeper CreateMode节点类型说明:
   * 1.PERSISTENT:持久型
   * 2.PERSISTENT_SEQUENTIAL:持久顺序型
   * 3.EPHEMERAL:临时型
   * 4.EPHEMERAL_SEQUENTIAL:临时顺序型
   * <p>
   * 1、2种类型客户端断开后不会消失
   * 3、4种类型客户端断开后超时时间内没有新的连接节点将会消失
   */

  /**
   * ZooKeeper ZooDefs.Ids权限类型说明:
   * OPEN_ACL_UNSAFE:完全开放的ACL,任何连接的客户端都可以操作该属性znode
   * CREATOR_ALL_ACL:只有创建者才有ACL权限
   * READ_ACL_UNSAFE:只能读取ACL
   */

  /**
   * ZooKeeper EventType事件类型说明:
   * NodeCreated:节点创建
   * NodeDataChanged:节点的数据变更
   * NodeChildrenChanged:子节点下的数据变更
   * NodeDeleted:子节点删除
   */

  /**
   * ZooKeeper KeeperState状态类型说明:
   * Disconnected:连接失败
   * SyncConnected:连接成功
   * AuthFailed:认证失败
   * Expired:会话过期
   */

  /**
   * 接收事件通知
   *
   * @param watchedEvent 事件通知
   */
  @Override
  public void process(WatchedEvent watchedEvent) {
    System.out.println("Receive WatchedEvent:" + watchedEvent);
    if (Event.KeeperState.SyncConnected == watchedEvent.getState()) {
      if (watchedEvent.getType() == Event.EventType.NodeChildrenChanged) {
        try {
          System.out.println("重新获取子节点:" + zooKeeper.getChildren(watchedEvent.getPath(), true));
        } catch (KeeperException e) {
          e.printStackTrace();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      countDownLatch.countDown();
    }
  }

  /**
   * 创建会话(最基础的实例)
   *
   * @throws Exception
   */
  @Test
  public void constructor_usage_simple() throws Exception {
    zooKeeper = new ZooKeeper(hosts, 5000, new ZooKeeperApi());
    System.out.println("ZooKeeper.state:" + zooKeeper.getState());
    countDownLatch.await();
    System.out.println("ZooKeeper session会话创建完成。");
  }

  /**
   * 创建会话(可复用sessionId的实例)
   *
   * @throws Exception
   */
  @Test
  public void constructor_usage_SID_PWD() throws Exception {
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi());
    System.out.println("ZooKeeper.state:" + zooKeeper.getState());
    countDownLatch.await();
    long sessionId = zooKeeper.getSessionId();
    byte[] sessionPasswd = zooKeeper.getSessionPasswd();
    System.out.println(String.format("首次获取sessionId:%s,sessionPasswd:%s", sessionId, sessionPasswd));
    // 使用不正确的sessionId
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi(), 1L, "123".getBytes());
    System.out.println("ZooKeeper.state err session:" + zooKeeper.getState());
    // 使用正确的sessionId
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi(), sessionId, sessionPasswd);
    System.out.println("ZooKeeper.state session:" + zooKeeper.getState());
    Thread.sleep(Integer.MAX_VALUE);
  }

  /**
   * 创建节点(同步)
   *
   * @throws Exception
   */
  @Test
  public void create_API_sync() throws Exception {
    String path = "/zk-create-znode-test-";
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi());
    System.out.println("ZooKeeper.state:" + zooKeeper.getState());
    countDownLatch.await();

    String path1 = zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    System.out.println("节点创建成功:" + path1);
    String path2 = zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
    System.out.println("节点创建成功:" + path2);
  }

  /**
   * 创建节点(异步)
   * 同步接口创建节点时需要考虑接口抛出异常的情况,
   * 异步接口的异常体现在回调函数的ResultCode响应码中,比同步接口更健壮。
   *
   * @throws Exception
   */
  @Test
  public void create_API_async() throws Exception {
    String path = "/zk-create-znode-test-";
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi());
    System.out.println("ZooKeeper.state:" + zooKeeper.getState());
    countDownLatch.await();

    zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,
        new CreateCallBack(), "ZooKeeper async create znode.");
    zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,
        new CreateCallBack(), "ZooKeeper async create znode.");
    zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,
        new CreateCallBack(), "ZooKeeper async create znode.");
    Thread.sleep(Integer.MAX_VALUE);
  }

  /**
   * 创建节点异步回调
   */
  class CreateCallBack implements AsyncCallback.StringCallback {
    /**
     * @param rc   服务端响应码 0:接口调用成功,-4:客户端与服务端连接已断开,-110:指定节点已存在,-112:会话已过期
     * @param path 调用接口时传入的节点路径(原样输出)
     * @param ctx  调用接口时传入的ctx值(原样输出)
     * @param name 实际在服务端创建的节点名
     */
    @Override
    public void processResult(int rc, String path, Object ctx, String name) {
      System.out.println("创建结果:rc=" + rc + ",path=" + path + ",ctx=" + ctx + ",name=" + name);
      if (rc == 0) {
        System.out.println("节点创建成功:" + name);
      } else if (rc == -4) {
        System.out.println("客户端与服务端连接已断开");
      } else if (rc == -110) {
        System.out.println("指定节点已存在");
      } else if (rc == -112) {
        System.out.println("会话已过期");
      } else {
        System.out.println("服务端响应码未知");
      }
    }
  }

  /**
   * 删除节点(同步)
   * 注:只允许删除叶子节点,不能直接删除根节点
   *
   * @throws Exception
   */
  @Test
  public void delete_API_sync() throws Exception {
    String path = "/zk-delete-znode-test";
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi());
    System.out.println("ZooKeeper state:" + zooKeeper.getState());
    countDownLatch.await();
    zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    zooKeeper.delete(path, -1);
    Thread.sleep(Integer.MAX_VALUE);
  }

  /**
   * 删除节点(异步)
   * 注:只允许删除叶子节点,不能直接删除根节点
   *
   * @throws Exception
   */
  @Test
  public void delete_API_async() throws Exception {
    String path = "/zk-delete-znode-test";
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi());
    System.out.println("ZooKeeper state:" + zooKeeper.getState());
    countDownLatch.await();
    zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    zooKeeper.delete(path, -1, new DeleteCallBack(), "ZooKeeper async delete znode");
    Thread.sleep(Integer.MAX_VALUE);
  }

  /**
   * 删除节点异步回调
   */
  class DeleteCallBack implements AsyncCallback.VoidCallback {
    /**
     * @param rc   服务端响应码 0:接口调用成功,-4:客户端与服务端连接已断开,-110:指定节点已存在,-112:会话已过期
     * @param path 调用接口时传入的节点路径(原样输出)
     * @param ctx  调用接口时传入的ctx值(原样输出)
     */
    @Override
    public void processResult(int rc, String path, Object ctx) {
      System.out.println("删除结果:rc=" + rc + ",path=" + path + ",ctx=" + ctx);
      if (rc == 0) {
        System.out.println("节点删除成功");
      } else if (rc == -4) {
        System.out.println("客户端与服务端连接已断开");
      } else if (rc == -112) {
        System.out.println("会话已过期");
      } else {
        System.out.println("服务端响应码未知");
      }
    }
  }

  /**
   * 获取子节点(同步)
   *
   * @throws Exception
   */
  @Test
  public void getChildren_API_sync() throws Exception {
    String path = "/zk-getChildren-sync-test";
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi());
    System.out.println("ZooKeeper state:" + zooKeeper.getState());
    countDownLatch.await();
    zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    zooKeeper.create(path + "/children1", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    List<String> childrenList = zooKeeper.getChildren(path, true);
    System.out.println("获取子节点:" + childrenList);
    zooKeeper.create(path + "/children2", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    Thread.sleep(Integer.MAX_VALUE);
  }

  /**
   * 获取子节点(异步)
   *
   * @throws Exception
   */
  @Test
  public void getChildren_API_async() throws Exception {
    String path = "/zk-getChildren-async-test";
    zooKeeper = new ZooKeeper(host, 5000, new ZooKeeperApi());
    System.out.println("ZooKeeper state:" + zooKeeper.getState());
    countDownLatch.await();
    zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    zooKeeper.create(path + "/children1", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    zooKeeper.getChildren(path, true, new ChildrenCallBack(), "异步获取子节点");
    zooKeeper.create(path + "/children2", "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    Thread.sleep(Integer.MAX_VALUE);
  }

  /**
   * 获取子节点异步回调
   */
  class ChildrenCallBack implements AsyncCallback.Children2Callback {
    /**
     * @param rc           服务端响应码 0:接口调用成功,-4:客户端与服务端连接已断开,-110:指定节点已存在,-112:会话已过期
     * @param path         调用接口时传入的节点路径(原样输出)
     * @param ctx          调用接口时传入的ctx值(原样输出)
     * @param childrenList 子节点列表
     * @param stat         节点状态,由服务器端响应的新stat替换
     */
    @Override
    public void processResult(int rc, String path, Object ctx, List<String> childrenList, Stat stat) {
      System.out.println("获取结果:rc=" + rc + ",path=" + path + ",ctx=" + ctx + ",childrenList=" + childrenList + ",stat=" + stat);
      if (rc == 0) {
        System.out.println("子节点获取成功:" + childrenList);
      } else if (rc == -4) {
        System.out.println("客户端与服务端连接已断开");
      } else if (rc == -112) {
        System.out.println("会话已过期");
      } else {
        System.out.println("服务端响应码未知");
      }
    }
  }

}

猜你喜欢

转载自www.cnblogs.com/54hsh/p/12196534.html