Curator是Zookeeper开源的客户端框架,封装了很多API,使用起来非常的方便,直接进入正题,讲解如何使用。
使用静态工厂方式进行创建,connectionInfo为Zookeeper地址,例如:127.0.0.1:2181
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient(connectionInfo, retryPolicy);
client.start();
方法名 | 描述 |
create() | 开始创建操作, 可以调用额外的方法(比如方式mode 或者后台执行background) 并在最后调用forPath()指定要操作的ZNode |
delete() | 开始删除操作. 可以调用额外的方法(版本或者后台处理version or background)并在最后调用forPath()指定要操作的ZNode |
checkExists() | 开始检查ZNode是否存在的操作. 可以调用额外的方法(监控或者后台处理)并在最后调用forPath()指定要操作的ZNode |
getData() | 开始获得ZNode节点数据的操作. 可以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的ZNode |
setData() | 开始设置ZNode节点数据的操作. 可以调用额外的方法(版本或者后台处理) 并在最后调用forPath()指定要操作的ZNode |
getChildren() | 开始获得ZNode的子节点列表。 以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的ZNode |
inTransaction() | 开始是原子ZooKeeper事务. 可以复合create, setData, check, and/or delete 等操作然后调用commit()作为一个原子操作提交 |
对上述接口进行了二次封装,写了个ZKClient工具类
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.transaction.CuratorTransaction;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
/**
* Created by wzj on 2018/5/4.
*/
public class ZKClient
{
/**
* 客户端
*/
private CuratorFramework client = null;
/**
* 构造方法
*
* @param connectionInfo zk主机
*/
public ZKClient(String connectionInfo)
{
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
client = CuratorFrameworkFactory.newClient(connectionInfo, retryPolicy);
client.start();
}
/**
* 创建节点
*
* @param path 路径
* @param createMode 节点类型
* @param data 节点数据
* @return 是否创建成功
*/
public boolean crateNode(String path, CreateMode createMode, String data)
{
try
{
client.create().withMode(createMode).forPath(path, data.getBytes());
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
/**
* 删除节点
*
* @param path 路径
* @return 删除结果
*/
public boolean deleteNode(String path)
{
try
{
client.delete().forPath(path);
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
/**
* 删除一个节点,并且递归删除其所有的子节点
*
* @param path 路径
* @return 删除结果
*/
public boolean deleteChildrenIfNeededNode(String path)
{
try
{
client.delete().deletingChildrenIfNeeded().forPath(path);
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
/**
* 判断节点是否存在
*
* @param path 路径
* @return true-存在 false-不存在
*/
public boolean isExistNode(String path)
{
try
{
Stat stat = client.checkExists().forPath(path);
return stat != null ? true : false;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
/**
* 判断节点是否是持久化节点
* @param path 路径
* @return 2-节点不存在 | 1-是持久化 | 0-临时节点
*/
public int isPersistentNode(String path)
{
try
{
Stat stat = client.checkExists().forPath(path);
if (stat == null)
{
return 2;
}
if (stat.getEphemeralOwner() > 0)
{
return 1;
}
return 0;
}
catch (Exception e)
{
e.printStackTrace();
return 2;
}
}
/**
* 获取节点数据
*
* @param path 路径
* @return 节点数据,如果出现异常,返回null
*/
public String getNodeData(String path)
{
try
{
byte[] bytes = client.getData().forPath(path);
return new String(bytes);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
/**
* 注册节点数据变化事件
*
* @param path 节点路径
* @param nodeCacheListener 监听事件
* @return 注册结果
*/
public boolean registerWatcherNodeChanged(String path, NodeCacheListener nodeCacheListener)
{
NodeCache nodeCache = new NodeCache(client, path, false);
try
{
nodeCache.getListenable().addListener(nodeCacheListener);
nodeCache.start(true);
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
/**
* 更新节点数据
*
* @param path 路径
* @param newValue 新的值
* @return 更新结果
*/
public boolean updateNodeData(String path, String newValue)
{
//判断节点是否存在
if (!isExistNode(path))
{
return false;
}
try
{
client.setData().forPath(path, newValue.getBytes());
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
/**
* 开启事务
*
* @return 返回当前事务
*/
public CuratorTransaction startTransaction()
{
return client.inTransaction();
}
}
增删改查每一个节点都是一个原子操作,一系列的原子操作就是一个事务。
在ZKClient增加获取事务方法
public CuratorTransaction startTransaction()
{
return client.inTransaction();
}
测试,构造三个原子操作
zkClient.startTransaction().create().forPath("/henan")
.and().create().forPath("/henan/zhengzhou")
.and().delete().forPath("/ads")
.and().commit();
只有三个原子操作都成功,三个操作才能最终执行。
将Zookeeper作为配置中心的时候,最常用的是监听节点数据的变动。
在ZKClient添加注册节点变动方法。
/**
* 注册节点数据变化事件
*
* @param path 节点路径
* @param nodeCacheListener 监听事件
* @return 注册结果
*/
public boolean registerWatcherNodeChanged(String path, NodeCacheListener nodeCacheListener)
{
NodeCache nodeCache = new NodeCache(client, path, false);
try
{
nodeCache.getListenable().addListener(nodeCacheListener);
nodeCache.start(true);
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
测试监听/zhejiang节点数据变动
zkClient.registerWatcherNodeChanged("/zhejiang", new NodeCacheListener()
{
@Override
public void nodeChanged() throws Exception
{
System.out.println("/zhejiang node data changeed,new data is = " + zkClient.getNodeData("/zhejiang"));
}
});
zkClient.updateNodeData("/zhejiang","hahah change1");
Demo代码下载链接: https://download.csdn.net/download/u010889616/10394855