Zookeeper——开源客户端ZkClient

ZooKeeper开源的客户端有ZkClient和Curator。我们先来学习一下ZkClient。
ZkClient
ZkClient在Zookeeper原生API接口上进行了包装,是一个更易用的ZooKeeper客户端。同时,ZkClient在内部实现了Session超时重连、Watcher反复注册等功能,使得ZooKeeper客户端的这些繁琐的细节工作对开发人员透明。
首先,需要引入ZkClient的Maven依赖:

<dependency>
			<groupId>com.101tec</groupId>
			<artifactId>zkclient</artifactId>
			<version>0.10</version>
		</dependency>

创建会话
在ZkClient中,有如下7种构造方法:

public ZkClient(String serverstring)
public ZkClient(String zkServers, int connectionTimeout)
public ZkClient(String zkServers, int sessionTimeout, int connectionTimeout)
public ZkClient(String zkServers, int sessionTimeout, int connectionTimeout, ZkSerializer zkSerializer)
public ZkClient(final String zkServers, final int sessionTimeout, final int connectionTimeout, final ZkSerializer zkSerializer, final long operationRetryTimeout)
public ZkClient(IZkConnection connection)
public ZkClient(IZkConnection connection, int connectionTimeout)
public ZkClient(IZkConnection zkConnection, int connectionTimeout, ZkSerializer zkSerializer)public ZkClient(final IZkConnection zkConnection, final int connectionTimeout, final ZkSerializer zkSerializer, final long operationRetryTimeout)

ZkClient构造方法参数说明:

参数名说明
zkServers指ZooKeeper服务器列表,由英文状态逗号分开的host:port字符串组成,每一个都代表一台ZooKeeper机器,如,192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181
sessionTimeout会话超时时间,单位为毫秒。默认是30000ms
connectionTimeout连接创建超时时间,单位为毫秒。此参数表明如果在这个时间段内还是无法和ZooKeeper建立连接,那么就放弃连接,直接抛出异常。
connectionIZkConnection接口的实现类
zkSerializer自定义序列化器

我们知道ZooKeeper原生API创建会话的时候,是一个异步的过程。而ZkClient通过内部包装,将这个异步的会话创建过程同步化了,这对于开发者的使用来说非常方便。
IZkConnection接口里面包含了添、删、改、查等一系列接口的定义。ZkClient默认提供对IZkConnection接口的两种实现,分别是ZkConnection和InMemoryConnection,前者是我们最常用的实现方式。通常开发人员不需要对IZkConnection进行改造,直接使用ZkConnection这个实现就可以完成绝大部分的业务需求。
我们之前提过,ZooKeeper的节点内容只支持字节数组(byte[])类型,也就是说,Zookeeper不负责为节点内容进行序列化,开发人员需要自己使用序列化工具将节点内容进行序列化和反序列化。ZkClient中定义了ZkSerializer接口,允许用户传入一个序列化实现,如Hessian或Kryo,默认情况下,ZkClient使用Java自带的序列化方式进行对象的序列化。
ZkClient和ZooKeeper原生构造方的最大区别,就是在ZkClient的构造方法中,不再提供传入Watcher对象的参数了。那么客户端如何去监听服务端的相关事件呢?ZkClient引入了大多数Java程序都使用过的Listener来实现Watcher注册。

创建节点
ZkClient提供了以下一系列接口来创建节点:

String create(final String path, Object data, final CreateMode mode)
String create(final String path, Object data, final List<ACL> acl, final CreateMode mode)
void createEphemeral(final String path)
void createEphemeral(final String path, final List<ACL> acl)
void createEphemeral(final String path, final Object data)
void createEphemeral(final String path, final Object data, final List<ACL> acl)
void createPersistent(String path, Object data)
void createPersistent(String path, boolean createParents)
void createPersistent(String path, Object data, List<ACL> acl)
String createPersistentSequential(String path, Object data)
String createPersistentSequential(String path, Object data, List<ACL> acl)
String createEphemeralSequential(final String path, final Object data)
String createEphemeralSequential(final String path, final Object data, final List<ACL> acl)

ZkClient create API参数说明:

参数名说明
path指定数据节点的节点路径,即API调用的目的是创建该节点
data节点的初始数据内容,可以传入null
mode节点类型,是一个枚举类型,通常有4种可选的节点类型
acl节点的ACL策略
createParents指定是否创建父节点
//创建节点
ZkClient zkClient = new ZkClient("47.96.164.224:2181", 5000);
zkClient.createPersistent("/zkclient/zkclient1/zkclient1-1", true);

设置createParents参数为true,表明需要递归创建父节点。

删除节点
在ZkClient中,可以通过以下API来删除指定节点:

boolean delete(final String path)
boolean deleteRecursive(String path)
boolean delete(final String path, final int version)

ZkClient delete API参数说明:

参数名说明
path数据节点的完整节点路径
version节点的版本号
//递归删除节点
zkClient.deleteRecursive("/zkclient");

读取数据
getChildren
在ZkClient中,可以通过以下API来获取指定节点的子节点列表:

List<String> getChildren(String path)

在获取子节点列表这个接口上,可以通过如下API来进行注册监听:

public List<String> subscribeChildChanges(String path, IZkChildListener listener)

通过该API的调用,就完成了事件监听的注册。从API方法中,可以看出,注册的是对子节点列表变更的监听,也就是说,一旦子节点列表发生变更,ZooKeeper服务端就会向客户端发出事件通知,由这个Listener来处理。如下是Listener接口的定义:

public interface IZkChildListener {

    /**
     * Called when the children of the given path changed.
     * 
     * @param parentPath
     *            The parent path
     * @param currentChilds
     *            The children or null if the root node (parent path) was deleted.
     * @throws Exception
     */
    public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception;
}
事件类型说明
新增子节点指定节点nodeA新增子节点,此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是最新的子节点列表(相对路径)
减少子节点指定节点nodeA减少子节点。此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是最新的子节点列表(相对路径),可能是null
删除节点指定节点nodeA被删除。此时在handleChildChange方法中,parentPath收到的是nodeA的全路径,currentChilds是null

如下示例:

zkClient.subscribeChildChanges("/zkclient", new IZkChildListener() {
			@Override
			public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
				System.out.println("parentPath======"+parentPath+"===="+currentChilds);
				for(String currentChild : currentChilds) {
					System.out.println("currentChild=========="+currentChild);
				}
			}
		});
zkClient.delete("/zkclient/zkclient1");
TimeUnit.SECONDS.sleep(1);

getData
在ZkClient中,可以通过以下API来获取指定节点的数据内容:

public <T extends Object> T readData(String path)
public <T extends Object> T readData(String path, boolean returnNullIfPathNotExists)
public <T extends Object> T readData(String path, Stat stat)

示例如:

zkClient.subscribeDataChanges("/zkclient", new IZkDataListener() {
			@Override
			public void handleDataDeleted(String dataPath) throws Exception {
				System.out.println("删除节点:"+dataPath);
			}
			
			@Override
			public void handleDataChange(String dataPath, Object data) throws Exception {
				System.out.println("节点名称:"+dataPath+",修改后的值:"+data);
			}
		});
zkClient.writeData("/zkclient", "hello");
TimeUnit.SECONDS.sleep(1);
boolean result = zkClient.deleteRecursive("/zkclient");
System.out.println("result====="+result);
TimeUnit.SECONDS.sleep(1);
Object obj = zkClient.readData("/zkclient/zkclient1");
System.out.println("obj===="+obj);
TimeUnit.SECONDS.sleep(1);

更新数据
在ZkClient中,可以通过以下API来更新指定节点的数据:

void writeData(String path, Object object)
void writeData(final String path, Object datat, final int expectedVersion)

ZkClient writeData API参数说明:

参数名说明
path数据节点的完整节点路径
data数据内容,可以是null
expectedVersion预期的数据版本,可以使用这个数据版本来实现类似CAS的原子操作

通过调用这个接口,就可以对指定节点进行数据更新了。

检测节点是否存在
在ZkClient中,可以通过以下API来检测指定节点是否存在:

boolean exists(final String path)

通过调用这个接口,就可以检测指定节点是否存在了。
———————————————————————————————————————————
阿里云福利

阿里云3月采购季:https://www.aliyun.com/acts/product-section-2019/new-users?userCode=litzwg4e
云主机2折
https://promotion.aliyun.com/ntms/act/qwbk.html?userCode=litzwg4e

阿里云自营建站,买一送一:https://www.aliyun.com/jianzhan/?userCode=litzwg4e
商标注册服务:https://tm.aliyun.com/?userCode=litzwg4e

作者:uk8692
来源:CSDN
原文:https://blog.csdn.net/uk8692/article/details/88032432
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值