/**
*
* @author liulei
* @since 2020-06-17
* @see ZookeeperUtils
*/
public class ZookeeperUtil extends ZookeeperUtils {
private static Logger logger = LoggerFactory.getLogger(ZookeeperUtil.class);
/**
* 同步创建持久化有序节点
*
* @param path 节点路径
* @param data 数据
* @return
*/
public static String createSequentialPersistentNode(String path, String data) {
Assert.hasText(path,"节点路径");
Assert.hasText(data,"节点数据");
CuratorFramework client = null;
try {
// 获取池中对象
client = ZookeeperClientPool.getInstance().borrowObject();
return client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath(path, data.getBytes());
} catch (Exception e) {
logger.error(String.format("同步创建持久化有序节点[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("同步创建持久化有序节点[%s]错误", path));
} finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
/**
* 同步创建临时节点(会话断开连接节点失效)
*
* @param path 节点路径
* @param data 数据
* @return
*/
public static String createEphemeralNode(String path, String data) {
Assert.hasText(path,"节点路径");
Assert.hasText(data,"节点数据");
CuratorFramework client = null;
try {
// 获取池中对象
client = ZookeeperClientPool.getInstance().borrowObject();
return client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(path, data.getBytes());
} catch (Exception e) {
logger.error(String.format("创建临时节点[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("创建临时节点[%s]错误", path));
} finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
/**
* 同步创建临时有序节点(会话断开连接节点失效)
*
* @param path 节点路径
* @param data 数据
* @return
*/
public static String createSequentialEphemeralNode(String path, String data) {
Assert.hasText(path,"节点路径");
Assert.hasText(data,"节点数据");
CuratorFramework client = null;
try {
// 获取池中对象
client = ZookeeperClientPool.getInstance().borrowObject();
return client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, data.getBytes());
} catch (Exception e) {
logger.error(String.format("创建临时节点[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("创建临时节点[%s]错误", path));
} finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
/**
* 同步更新数据
*
* @param path
* @param data
*/
public static void updateData(String path, String data) {
Assert.hasText(path,"节点路径");
Assert.hasText(data,"节点数据");
CuratorFramework client = null;
try {
// 获取池中对象
client = ZookeeperClientPool.getInstance().borrowObject();
client.setData().forPath(path, null == data ? null : data.getBytes());
} catch (Exception e) {
logger.error(String.format("更新节点数据[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("更新节点数据[%s]错误", path));
} finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
/**
* 同步强制删除一个zookeeper节点同时递归删除子节点
*
* @param path
*/
public static void deleteAllNode(String path){
Assert.hasText(path,"节点路径");
CuratorFramework client = null;
try {// 获取池中对象
client = ZookeeperClientPool.getInstance().borrowObject();
client.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);
} catch (Exception e) {
logger.error(String.format("删除节点[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("删除节点[%s]错误", path));
} finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
/**
* 同步获取节点的所有子节点
*
* @param path
* @return 返回所有子节点的节点名
*/
public static List getChildren(String path){
Assert.hasText(path,"节点路径");
CuratorFramework client = null;
try {
// 获取池中对象
client = ZookeeperClientPool.getInstance().borrowObject();
return client.getChildren().forPath(path);
} catch (Exception e) {
logger.error(String.format("获取节点下的子节点[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("获取节点下的子节点[%s]错误", path));
} finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
/**
* 对指定节点进行监听
*
* @param path 节点路径
* @return
*/
public static NodeCache registerNodeCacheListener(String path){
Assert.hasText(path,"节点路径");
CuratorFramework client = null;
try {
// 获取池中对象
client = ZookeeperClientPool.getInstance().borrowObject();
NodeCache nodeCache = new NodeCache(client, path);
nodeCache.getListenable().addListener(new NodeCacheListener(){
@Override
public void nodeChanged() throws Exception {
logger.info("节点{}成功监听节点数据变化",path);
}
});
nodeCache.start();
return nodeCache;
} catch (Exception e) {
logger.error(String.format("对指定节点进行监听[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("对指定节点进行监听[%s]错误", path));
} finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
/**
* 对指定路径节点的一级子目录监听,不对该节点的操作监听
*
* @param path
* @param listener
* @return
*/
public static PathChildrenCache registerPathChildListener(String path, PathChildrenCacheListener listener){
Assert.hasText(path,"节点路径");
CuratorFramework client = null;
try {
// 获取池中对象
client = ZookeeperClientPool.getInstance().borrowObject();
PathChildrenCache pathChildrenCache = new PathChildrenCache(client, path,true);
pathChildrenCache.getListenable().addListener(listener);
pathChildrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
return pathChildrenCache;
} catch (Exception e) {
logger.error(String.format("对指定路径节点的一级子目录监听[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("对指定路径节点的一级子目录监听[%s]错误", path));
}finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
/**
* 注册目录监听器
*
* @param path
* @param maxDepth 节点深度
* @param listener
* @return
*/
public static TreeCache registerTreeCacheListener(String path, int maxDepth, TreeCacheListener listener){
Assert.hasText(path,"节点路径");
CuratorFramework client = null;
try {
TreeCache treeCache = TreeCache.newBuilder(client,path)
.setCacheData(true)
.setMaxDepth(maxDepth)
.build();
treeCache.getListenable().addListener(listener);
treeCache.start();
return treeCache;
} catch (Exception e) {
logger.error(String.format("注册目录监听器[%s]错误", path), e);
throw new BizException(ErrorCode.ZK_CLIENT_OP_ERROR_CODE, String.format("注册目录监听器[%s]错误", path));
}finally {
// 归还池中对象
ZookeeperClientPool.getInstance().returnObject(client);
}
}
}
/**
* zookeeper节点接听
*
* @author liulei
* @since 2020-06-17
**/
@Component
public class ZookeeperNodeListener implements InitializingBean, DisposableBean {
private static final String rootPath = "/";
private static Logger logger = LoggerFactory.getLogger(ZookeeperNodeListener.class);
@Autowired
private TreeCache treeCache;
@Override
public void afterPropertiesSet() throws Exception {
treeCache = ZookeeperUtil.registerTreeCacheListener(rootPath,10,new TreeCacheListener(){
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
try {
ChildData childData = event.getData();
String path = childData.getPath();
String data = new String(childData.getData());
data = StringUtils.isBlank(data) ? "" : data;
switch (event.getType()) {
case NODE_ADDED:
logger.info("正在新增子节点路径: {}, 数据:{}",path,data);
break;
case NODE_UPDATED:
logger.info("正在更新子节点: {}, 数据:{}",path,data);
break;
case NODE_REMOVED:
logger.info("正在删除子节点: {}, 数据:{}",path,data);
break;
case CONNECTION_LOST:
logger.info("节点: {}连接丢失",rootPath);
break;
case CONNECTION_RECONNECTED:
logger.info("节点: {}恢复连接",rootPath);
break;
}
} catch (Exception e) {
logger.error(e.getMessage(),e);
}
}
});
// 没有中断标记
while (!Thread.currentThread().isInterrupted()){
TimeUnit.SECONDS.sleep(1);
}
}
@Override
public void destroy() throws Exception {
if(treeCache != null){
treeCache.close();
}
}
}