使用Java客户端API操作Zookeeper

在了解了使用zkCli操作zookeeper之后,下面就是使用Java来操作zookeeper。就像操作数据库一样,数据库可以使用客户端工具来连接,也可以提供Java的api来链接。至于为什么要使用Java来连接,这里就不必多说了,就好像为什么要使用Java链接数据库一样。

准备环境

同样还是类比数据库,我们在连接数据库的时候首先要导入连接数据库的jar包,那么对于连接zookeeper也是同样,也需要导入zookeeper的jar包,但不同的是,zookeeper还依赖一些其他的第三方包,我们在使用的时候也要一同导入进来。比如记录日志的slf4j等。不过在zookeeper的发布包中已经给我们带着了,所以我们也不需要去下载。

这里为了方便使用maven来管理的朋友,把坐标贴上

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.10</version>
    <type>jar</type>
</dependency>

在开始对zookeeper进行操作之前先来搭建环境。这里就是Jdk1.8+Eclipse+Win10.项目没有使用maven,而是直接从运行包中拷贝出来的jar

连接到zookeeper

要对zookeeper进行操作,首先要连接到zookeeper。就像数据库一样,也有一个连接的过程。下面是一个创建zookeeper连接的代码。

image

这里核心的代码就是第18行,创建zookeeper的代码。实例化一个zookeeper实例,就是创建了一个连接,这里需要指定连接的字符串超时时间和一个watch接口。zookeeper的连接和数据库的连接不同,数据库通过DriverManager的getConnect方法就可以直接获取到连接,但zookeeper在获取连接的过程中,使用了Future。也就意味着,new之后所拿到的仅仅是一个zookeeper对象,而这个对象可能还没有连接到zookeeper服务。

这么说,zookeeper的连接过程可能会受到网络,zookeeper集群各种问题的影响,连接的过程可能会比较慢,因此,为了提高程序的执行性能,在new的时候就给你一个协议,你可以通过这个协议,来拿到连接。这里其实就是一个Futrue模式,如果对Future不是很了解的朋友可以去网络上找些资料学习。

为了我们能够拿到真实可用的zookeeper对象,我们这里使用了CountDownLatch,这是一个并发工具类,在初始化的时候指定一个int类型的值,每次调用countDown方法,这个值都会减一,当减到0时,所有的await线程都会被叫醒。

当连接成功之后,zookeeper会发出一个通知,所以我们要定义一个观察者(Watch)来监听这个通知,这就是代码第11行的implements Watcher的原因。 Watcher接口中有一个process方法,在这个方法中,当我们监听到连接成功,就把CountDownLatch的值减1,这样,第21行的代码就会被叫醒,于是就返回zookeeper实例成功。

这就是连接zookeeper的整个过程。这里涉及到了多线程并发相关的内容比较多,如果你对多线程并发相关的内容不够了解,看这段代码可能还是会有些困惑的。

创建节点

连接上了zookeeper之后,我们就可以像使用zkCli一样操作zookeeper了,首先就是创建节点,比如我们要创建一个/javaclient的节点,并将内容指定为hello java,我们就可以这么做

image

这里主要是调用了zookeeper的create方法,方法的参数如下:

  • path String znode节点的路径
  • data byte[] znode节点的内容
  • acl List 访问权限
  • createModel CreateModel 创建模式

这里不去介绍zookeeper的原理,因此对于acl,可以使用Ids提供的常量就可以了。对于createModel是一个枚举类,可以直接使用。

在创建的过程中,不能够递归创建。只能一层一层的创建。如果要创建/app1/host.如果/app1不存在,则创建不成功。对于删除也是同样。

查询节点

查询节点有两层,第一个是相当于zkCli的get,就是获取某个节点的值。还有一个就是类似于ls,列出子节点。

获取子节点的内容

获取子节点的内容可以通过zookeeper的getData方法,getData方法有多个重载,主要就是分为直接获取和异步获取,异步获取多了一个回掉,直接获取则直接返回获取的结果。下面是一个直接获取的例子。

image

第50行,zoo.getData返回值是一个byte类型的数组,因此使用了new String(Byte[]) 构造一个字符串,然后对这个字符串进行控制台输出。

下面是带回调的数据获取

image

这里要注意,一定要休眠,否则在看不到结果之前可能程序就停掉了。

列出子节点

就像我们使用File类的listFile一样,在zookeeper中,可以列出子节点,代码如下

image

有了子节点的名字之后,就可以递归的遍历了。

修改节点

使用JavaAPI对zookeeper节点的修改也是非常简单的。和getData类似,setData也有两种模式,一种是直接修改,另外一种是异步修改,异步修改之后可以通过回调将修改后的数据带回。这里仅演示同步修改。

image

setData的参数

  • path String 修改的节点
  • data byte[] 修改的内容
  • version int 数据当前的版本

这里主要说的是version,这里的version指的是znode节点的dataVersion的值,每次数据的修改都会更新这个值,主要是为了保证一致性,具体请了解CAS。通俗来讲就是如果你指定的version比保持的version值小,则表示已经有其他线程所更新了,你也就不能更新成功了,否则则可以更新成功。如果你不管别的线程有没有更新成功都要更新这个节点的值,则version可以指定为-1

关于Watcher

我们在get的时候,看到有参数为Watcher,这里Watcher是干嘛的呢,就是可以在数据做了修改之后,zookeeper会发出通知,那么注册的Wacher就可以接收到数据的修改。

删除节点

对于节点的删除,同样有同步删除和异步删除,异步删除比同步删除多了一个回调。这里仅演示同步删除,代码如下

image

注意删除这里也有一个version,这个version和setData的version意义相同。

删除不能够递归删除,只能一层一层删除。

到这里对与使用Java客户端API操作zookeeper就完成了,内容比较简单,不足之处还请各位大神指正!

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐