【Zookeeper】 在Java中的操作

  • 一、基本功能演示

    • 1.1 Maven依赖信息
    • 1.2 代码演示
      • 方法说明
    • 1.3 创建Zookeeper节点信息
  • 二、Watcher
    • 2.1 什么是Watcher接口
    • 2.2 Watcher代码

一、基本功能演示

1.1 Maven依赖信息

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

1.2 代码演示

public class Test001 {

    private static final String CONNECTSTRING = "127.0.0.1:2181";
    private static final int SESSIONTIMEOUT =  5000;
    //信号量,阻塞程序执行,用户等待zookeeper连接成功,发送成功信号,
    private static final CountDownLatch countDownLatch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {
        ZooKeeper zooKeeper = null;
        try {
            //1.Zookeeper创建了一连接
            zooKeeper = new ZooKeeper(CONNECTSTRING, SESSIONTIMEOUT, new Watcher() {

                @Override
                public void process(WatchedEvent event) {
                    //监听节点是否发生变化

                    // 获取事件状态
                    KeeperState keeperState = event.getState();
                    // 获取事件类型
                    EventType eventType = event.getType();
                    if (KeeperState.SyncConnected == keeperState) {
                        if (EventType.None == eventType) {
                            countDownLatch.countDown();//调用该方法会减一,如果为0的话
                            System.out.println("zk 启动连接...");
                        }

                    }

                }
            });

            // 2.
            //节点类型:
            // 1. CreateMode . EPHEMERAL创建- -个临时节点
            // 2.CreateMode. EPHEMERAL _SEQUENTIAL 如果节点发生重复的情况下,会自动id自增保证唯- -性
            // 3.CreateMode . PERSISTENT持久类型永久保存在硬盘上
            // 4.CreateMode. PERSISTENT SEQUENTIAL持久类型如果节点发生重复的情况下,会自动id自增保证唯一性

            countDownLatch.await();//如果计数器不为0,则一直等待
            String nodeResult = zooKeeper.create("/test", "zhangsan".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            System.out.println("节点名称:"+nodeResult);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(zooKeeper!=null) {
                zooKeeper.close();
            }

        }

    }
}

方法说明

创建节点(znode) 方法:
create(String path, byte[] data, List<ACL> acl, CreateMode createMode) throws KeeperException, InterruptedException

提供了两套创建节点的方法,同步和异步创建节点方式。
同步方式:
* 参数1,节点路径名称 : InodeName (不允许递归创建节点,也就是说在父节点不存在的情况下,不允许创建子节点)
* 参数2,节点内容: 要求类型是字节数组(也就是说,不支持序列化方式,如果需要实现序列化,可使用java相关序列化框架,如Hessian、Kryo框架)
* 参数3,节点权限: 使用Ids.OPEN_ACL_UNSAFE开放权限即可。(这个参数一般在权展
没有太高要求的场景下,没必要关注)
* 参数4,节点类型: 创建节点的类型: CreateMode,提供四种节点类型
   * PERSISTENT                   持久化节点
   * PERSISTENT_SEQUENTIAL        顺序自动编号持久化节点,这种节点会根据当前已存在的节点数自动加 1
   * EPHEMERAL                    临时节点, 客户端session超时这类节点就会被自动删除
   * EPHEMERAL_SEQUENTIAL         临时自动编号节点

1.3 创建Zookeeper节点信息

//1. 创建持久节点,并且允许任何服务器可以操作
String result = zk.create("/haoworld", "Lasting".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("result:" + result);
//2. 创建临时节点
String result = zk.create("/haoworld_tmp", "temp".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("result:" + result);

二、Watcher

  • 在ZooKeeper中,接口类Watcher用于表示一个标准的事件处理器,其定义了事件通知相关的逻辑,包含KeeperState和EventType两个枚举类,分别代表了通知状态和事件类型,同时定义了事件的回调方法:process(WatchedEvent event)。

2.1 什么是Watcher接口

同一个事件类型在不同的通知状态中代表的含义有所不同,表7-3列举了常见的通知状态和事件类型。
Watcher通知状态与事件类型一览

![-w735](media/15681306896776/15681308320378.jpg)?

表中列举了ZooKeeper中最常见的几个通知状态和事件类型。

  • 回调方法process()

    • process方法是Watcher接口中的一个回调方法,当ZooKeeper向客户端发送一个Watcher事件通知时,客户端就会对相应的process方法进行回调,从而实现对事件的处理。process方法的定义如下:
  • abstract public void process(WatchedEvent event);
    • 这个回调方法的定义非常简单,我们重点看下方法的参数定义:WatchedEvent。WatchedEvent包含了每一个事件的三个基本属性:通知状态(keeperState),事件类型(EventType)和节点路径(path),。ZooKeeper使用WatchedEvent对象来封装服务端事件并传递给Watcher,从而方便回调方法process对服务端事件进行处理。
      提到WatchedEvent,不得不讲下WatcherEvent实体。笼统地讲,两者表示的是同一个事物,都是对一个服务端事件的封装。不同的是,WatchedEvent是一个逻辑事件,用于服务端和客户端程序执行过程中所需的逻辑对象,而WatcherEvent因为实现了序列化接口,因此可以用于网络传输。
      服务端在生成WatchedEvent事件之后,会调用getWrapper方法将自己包装成一个可序列化的WatcherEvent事件,以便通过网络传输到客户端。客户端在接收到服务端的这个事件对象后,首先会将WatcherEvent还原成一个WatchedEvent事件,并传递给process方法处理,回调方法process根据入参就能够解析出完整的服务端事件了。
      需要注意的一点是,无论是WatchedEvent还是WatcherEvent,其对ZooKeeper服务端事件的封装都是机及其简单的。举个例子来说,当/zk-book这个节点的数据发生变更时,服务端会发送给客户端一个“ZNode数据内容变更”事件,客户端只能够接收到如下信

2.2 Watcher代码

public class ZkClientWatcher implements Watcher {
        // 集群连接地址
        private static final String CONNECT_ADDRES = "192.168.110.159:2181,192.168.110.160:2181,192.168.110.162:2181";
        // 会话超时时间
        private static final int SESSIONTIME = 2000;
        // 信号量,让zk在连接之前等待,连接成功后才能往下走.
        private static final CountDownLatch countDownLatch = new CountDownLatch(1);
        private static String LOG_MAIN = "【main】 ";
        private ZooKeeper zk;

    public void createConnection(String connectAddres, int sessionTimeOut) {
        try {
            zk = new ZooKeeper(connectAddres, sessionTimeOut, this);
            System.out.println(LOG_MAIN + "zk 开始启动连接服务器....");
            countDownLatch.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean createPath(String path, String data) {
        try {
            this.exists(path, true);
            this.zk.create(path, data.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            System.out.println(LOG_MAIN + "节点创建成功, Path:" + path + ",data:" + data);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 判断指定节点是否存在
     *
     * @param path
     *            节点路径
     */
    public Stat exists(String path, boolean needWatch) {
        try {
            return this.zk.exists(path, needWatch);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public boolean updateNode(String path,String data) throws KeeperException, InterruptedException {
        exists(path, true);
        this.zk.setData(path, data.getBytes(), -1);
        return false;
    }

    public void process(WatchedEvent watchedEvent) {

        // 获取事件状态
        KeeperState keeperState = watchedEvent.getState();
        // 获取事件类型
        EventType eventType = watchedEvent.getType();
        // zk 路径
        String path = watchedEvent.getPath();
        System.out.println("进入到 process() keeperState:" + keeperState + ", eventType:" + eventType + ", path:" + path);
        // 判断是否建立连接
        if (KeeperState.SyncConnected == keeperState) {
            if (EventType.None == eventType) {
                // 如果建立建立成功,让后程序往下走
                System.out.println(LOG_MAIN + "zk 建立连接成功!");
                countDownLatch.countDown();
            } else if (EventType.NodeCreated == eventType) {
                System.out.println(LOG_MAIN + "事件通知,新增node节点" + path);
            } else if (EventType.NodeDataChanged == eventType) {
                System.out.println(LOG_MAIN + "事件通知,当前node节点" + path + "被修改....");
            }
            else if (EventType.NodeDeleted == eventType) {
                System.out.println(LOG_MAIN + "事件通知,当前node节点" + path + "被删除....");
            }

        }
        System.out.println("--------------------------------------------------------");
    }

    public static void main(String[] args) throws KeeperException, InterruptedException {
        ZkClientWatcher zkClientWatcher = new ZkClientWatcher();
        zkClientWatcher.createConnection(CONNECT_ADDRES, SESSIONTIME);
    //      boolean createResult = zkClientWatcher.createPath("/p15", "pa-644064");
            zkClientWatcher.updateNode("/pa2","7894561");
        }

    }

原文地址:https://www.cnblogs.com/haoworld/p/zookeeper-zaijava-zhong-de-cao-zuo.html

时间: 2024-10-08 20:35:36

【Zookeeper】 在Java中的操作的相关文章

java中文件操作《一》

在日常的开发中我们经常会碰到对文件的操作,在java中对文件的操作都在java.io包下,这个包下的类有File.inputStream.outputStream.FileInputStream.FileOutputStream.reader.writer.FileReader.FileWriter等等,其中对文件的操作又分为两大类,一类是字符流,一类是字节流.所谓的字符流是以字节(8b)为单位进行读/写,字符流即使用字符为单位读/写,java使用unicode编码,一个字符两个字节,下面分别对

Java中数组操作 java.util.Arrays 类常用方法的使用

任何一门编程语言,数组都是最重要和常用的数据结构之一,但不同的语言对数组的构造与处理是不尽相同的. Java中提供了java.util.Arrays 类能方便地操作数组,并且它提供的所有方法都是静态的.下面介绍一下Arrays类最常用的几个方法. 1.  数组排序 Arrays工具类提供了一个sort方法,只需要一行代码即可完成排序功能. 2.  数组转换为字符串 Arrays提供了一个toString方法,可以直接把一个数组转换为字符串,这样可以方便观察数组里的元素. //来源:公众号[时光与

在Java中如何操作word, excel, pdf文件

java操作word,excel,pdf 在平常应用程序中,对office和pdf文档进行读取数据是比较常见的功能,尤其在很多web应用程序中.所以今天我们就简单来看一下java对word.excel.pdf文件的读取.本篇博客只是讲解简单应用.如果想深入了解原理.请读者自行研究一些相关源码. 首先我们来认识一下读取相关文档的jar包: 1. 引用POI包读取word文档内容 poi.jar 下载地址 http://apache.freelamp.com/poi/release/bin/poi-

java中XML操作:xml与string互转、读取XML文档节点及对XML节点增删改查

一.XML和String互转: 使用dom4j程式变得很简单 //字符串转XML String xmlStr = \"......\"; Document document = DocumentHelper.parseText(xmlStr); // XML转字符串 Document document = ...; String text = document.asXML(); //这里的XML DOCUMENT为org.dom4j.Document 二.读取XML文档节点: pack

java中并发操作

java的并发操作中,主要在java.util.concurrent包中. 比如常见的ScheduledExecutorService,简单来说,这是一个执行定时任务的线程,可以参考这篇博文:https://blog.csdn.net/wangmx1993328/article/details/80840598,这个类适合于在分布式系统中定时发送心跳的操作.同时还有个简单的Timer和TimerTask类:https://blog.csdn.net/wangmx1993328/article/d

java中执行操作javascript

使用操作 使用前确认必须是server2008 64位系统 并且jdk是64位的,如果是32位的那么是不可以使用该jar的 1. j2v8_win32_x86_64-4.5.0.jar 中的dll取出并改名为j2v8_win32_x86_64.dll 2. 将j2v8_win32_x86_64.dll 放到jdk的jre的bin目录下 3. 以上完成既可以使用了 以下是一个简单的demo System.out.println(1111); System.out.println("5jn9vc31

Java中Jedis操作Redis与Spring的整合

Redis是一个key-value存储系统.它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合)和zset(有序集合).这些数据类型都支持push/pop.add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的.在此基础上,redis支持各种不同方式的排序.为了保证效率,数据都是缓存在内存中.redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步.以下是

java中IO操作

File类 /** * 路径分隔符:public static final String separator; * 设置文件路径:public File(String pathName) ; * 创建文件:public boolean creatNewFile() throws IOException; * 判断文件是否存在:public boolean exists(); * 删除文件:public boolean delete(); * 找到父路径:public File getPareen

【深入JAVA】Java中文件操作

在阅读的过程中有任何问题,欢迎一起交流 邮箱:[email protected]    QQ:1494713801 1.在指定目录下创建文件夹及文件,并写入初始内容 File file = new File("filePath"); File pf = file.getParentFile(); if(!pf.exists()){ pf.mkdirs();//创建文件夹 } if(!file.exists()){ file.createNewFile();//创建新文件 } FileW