Curator,提供给Java操作ZK的API组件:

需要的组件依赖:

        <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.2.0</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.2.0</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.32</version>
<scope>test</scope>
</dependency>

Curator要求配置日志组件,当然不配也是可以的

Log4J还要求配置log4j.properties,配置文件是随便找的

# priority  :debug<info<warn<error
#you cannot specify every priority with different file for log4j
log4j.rootLogger=debug,stdout,info,debug,warn,error #console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= [%d{yyyy-MM-dd HH:mm:ss a}]:%p %l%m%n
#info log
log4j.logger.info=info
log4j.appender.info=org.apache.log4j.DailyRollingFileAppender
log4j.appender.info.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.info.File=./src/com/hp/log/info.log
log4j.appender.info.Append=true
log4j.appender.info.Threshold=INFO
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#debug log
log4j.logger.debug=debug
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.debug.File=./src/com/hp/log/debug.log
log4j.appender.debug.Append=true
log4j.appender.debug.Threshold=DEBUG
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#warn log
log4j.logger.warn=warn
log4j.appender.warn=org.apache.log4j.DailyRollingFileAppender
log4j.appender.warn.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.warn.File=./src/com/hp/log/warn.log
log4j.appender.warn.Append=true
log4j.appender.warn.Threshold=WARN
log4j.appender.warn.layout=org.apache.log4j.PatternLayout
log4j.appender.warn.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n
#error
log4j.logger.error=error
log4j.appender.error = org.apache.log4j.DailyRollingFileAppender
log4j.appender.error.DatePattern='_'yyyy-MM-dd'.log'
log4j.appender.error.File = ./src/com/hp/log/error.log
log4j.appender.error.Append = true
log4j.appender.error.Threshold = ERROR
log4j.appender.error.layout = org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss a} [Thread: %t][ Class:%c >> Method: %l ]%n%p:%m%n

API操作:

创建连接:

第一种,根据构造参数创建客户端对象

第二种,使用构建工厂管理创建客户端对象

    /**
* 创建节点一
*
*/
@Test
public void establishConnection1() {
/**
* 方式一
* String connectString,
* 单例参数 "192.168.242.101:2181"
* 集群参数 "192.168.242.101:2181, 192.168.242.102:2181, 192.168.242.103:2181"
* int sessionTimeoutMs,
* 回话超时限制
* int connectionTimeoutMs,
* 连接超时限制
* RetryPolicy retryPolicy, ZKClientConfig zkClientConfig
* 重新连接策略
*
*/
ExponentialBackoffRetry exponentialBackoffRetry = new ExponentialBackoffRetry(3000, 10);// 3秒 10次 CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(
"192.168.242.101:2181",
1000 * 60, // 1分钟
1000 * 15, // 15秒
exponentialBackoffRetry
); curatorFramework.start(); // 建立连接
} /**
* 创建节点二
*
*
*/
@Test
public void establishConnection2() {
CuratorFramework curatorFramework = CuratorFrameworkFactory
.builder()
.sessionTimeoutMs(1000 * 60)
.connectionTimeoutMs(1000 * 15)
.connectString("192.168.242.101:2181")
.retryPolicy(new ExponentialBackoffRetry(3000, 10))
.namespace("nmNode") // 指定在一个节点下进行操作
.build(); curatorFramework.start();
}

为便于操作Zookeeper,使用Junit的前置调用和后置调用注解:

创建资源和释放资源

    CuratorFramework zookeeperClient;

@Before
public void prepareConnection() {
zookeeperClient = CuratorFrameworkFactory
.builder()
.sessionTimeoutMs(1000 * 60)
.connectionTimeoutMs(1000 * 15)
.connectString("192.168.242.101:2181")
.retryPolicy(new ExponentialBackoffRetry(3000, 10))
.namespace("nmNode") // 指定在一个节点下进行操作
.build(); zookeeperClient.start();
} @After
public void afterSettleConnection() {
if (zookeeperClient != null) zookeeperClient.close();
}

创建ZK节点:

    /**
* 创建节点操作
*
*/
@Test
public void createNodeAPI() {
String forPath = null;
try {
// 纯创建节点
forPath = zookeeperClient.create().forPath("/node1");
System.out.println(forPath); // 创建带数据的节点
forPath = zookeeperClient.create().forPath("/node2", "node with data".getBytes(StandardCharsets.UTF_8));
System.out.println(forPath);
/**
* 指定模式
* CreateMode
* PERSISTENT(0, false, false, false, false),
* PERSISTENT_SEQUENTIAL 持久化顺序模式
* EPHEMERAL 临时模式
* EPHEMERAL_SEQUENTIAL 临时顺序模式
* CONTAINER 容器模式
* PERSISTENT_WITH_TTL 持久化超时模式
* PERSISTENT_SEQUENTIAL_WITH_TTL 持久化顺序超时模式
*/
forPath = zookeeperClient
.create()
.withMode(CreateMode.PERSISTENT)
.forPath("/node2", "node with data".getBytes(StandardCharsets.UTF_8));
System.out.println(forPath); /**
* 创建多级节点
* .creatingParentsIfNeeded()
*/
forPath = zookeeperClient
.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT)
.forPath("/node2/subNode1/subSubNode1", "node with data2".getBytes(StandardCharsets.UTF_8));
System.out.println(forPath);
} catch (Exception exception) {
exception.printStackTrace();
}
}

查询ZK节点:

    /**
* 查询节点
*/
@Test
public void queryNodes() {
byte[] data = null;
try {
// 获取该节点下的数据
data = zookeeperClient.getData().forPath("/node2");
System.out.println(new String(data, StandardCharsets.UTF_8)); /**
* 获取该节点下的子节点
*
* 注意使用/根节点表示时,namespace("nmNode")的影响
* zookeeperClient.getChildren().forPath("/")
*/
List<String> strings = zookeeperClient.getChildren().forPath("/node1");
System.out.println(strings); /**
* ls -s 节点
* 查询节点状态
*
* stat空参数表示 0 0 0 0 0 初始状态
*/
Stat stat = new Stat(); // 携带构造后会进行赋值操作
zookeeperClient.getData().storingStatIn(stat).forPath("/node2");
System.out.println(stat); // 52,52,1635080231927,1635080231927,0,4,0,0,14,4,73 } catch (Exception e) {
e.printStackTrace();
}
}

修改节点:

    /**
* 修改节点
*/
@Test
public void updateNode() {
try {
/**
* 简单修改节点值
*/
Stat stat = zookeeperClient.setData().forPath("/node1/subNode1", "changes Data".getBytes(StandardCharsets.UTF_8)); /**
* 乐观锁控制
* getVersion
*/
String subNode2 = "/node1/subNode1";
Stat subStat = new Stat();
zookeeperClient.getData().storingStatIn(subStat);
zookeeperClient.setData().withVersion(subStat.getVersion()).forPath(subNode2, "changes Data2".getBytes(StandardCharsets.UTF_8)); } catch (Exception exception) {
exception.printStackTrace();
}
}

删除ZK节点

    /**
* 删除节点
*
*
*/
@Test
public void deleteNode() { try { /**
* 普通删除 /node1/subNode1
*
* 该节点带有子节点则报错,不能被删除
* KeeperErrorCode = Directory not empty for /nmNode/node1
* */
// Void unused = zookeeperClient.delete().forPath("/node1"); /**
* 带节点全部删除
*
*/
// zookeeperClient.delete().deletingChildrenIfNeeded().forPath("/node2"); // 带保证的删除? 防止网络抖动断开连接,会调用重试删除
zookeeperClient.delete().guaranteed().forPath("delete success"); // 删除成功的回调处理
zookeeperClient.delete().guaranteed().inBackground(new BackgroundCallback() {
// 操作成功时将执行回调
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("delete success"); }
}).forPath("/node1"); } catch (Exception exception) {
exception.printStackTrace();
} }

监听节点:

    @Test
@SuppressWarnings("deprecation")
public void listeningFeature() { // nodeCache 被标注为已过时方法
NodeCache nodeCache = new NodeCache(zookeeperClient, "/node1"); // Listenable<使用这个泛型只能声明一种监听类型> listenable = nodeCache.getListenable();
Listenable listenable = nodeCache.getListenable(); // 绑定监听事件
listenable.addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
String path = nodeCache.getPath();
System.out.println("this node changed: " + path); // 获取变化后的数据
byte[] data = nodeCache.getCurrentData().getData();
System.out.println("after change, data is " + new String(data, StandardCharsets.UTF_8));
}
}); // 绑定子节点监听事件
listenable.addListener(new PathChildrenCacheListener() { @Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
System.out.println("subNode changed, event -> " + pathChildrenCacheEvent); // 获取子节点事件类型
PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType(); // 如果是修改事件触发,则开始执行XXX。。。
if (PathChildrenCacheEvent.Type.CHILD_UPDATED .equals(type)) {
byte[] data = pathChildrenCacheEvent.getData().getData();
System.out.println("new Data -> " + new String(data, StandardCharsets.UTF_8));
}
}
}); // 绑定树节点监听事件 一般直接监听当前命名空间的全部节点
TreeCache treeCache = new TreeCache(zookeeperClient, "/");
Listenable<TreeCacheListener> listenable1 = treeCache.getListenable();
listenable1.addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
System.out.println("changed");
System.out.println(treeCacheEvent);
}
});
}

【Zookeeper】Re02 CuratorAPI的更多相关文章

  1. 【Zookeeper】源码分析目录

    Zookeeper源码分析目录如下 1. [Zookeeper]源码分析之序列化 2. [Zookeeper]源码分析之持久化(一)之FileTxnLog 3. [Zookeeper]源码分析之持久化 ...

  2. 【Zookeeper】基础学习概览【汇总】

    一.概述 1.1 简介 1.2 Zookeeper集群机制 1.3 Zookeeper特性 二.Zookeeper应用场景 三.Zookeeper数据结构 四.Zookeeper安装 五.Java操作 ...

  3. 【Zookeeper】 在Java中的操作

    一.基本功能演示 1.1 Maven依赖信息 1.2 代码演示 方法说明 1.3 创建Zookeeper节点信息 二.Watcher 2.1 什么是Watcher接口 2.2 Watcher代码 一. ...

  4. 【Zookeeper】编程实战之Zookeeper分布式锁实现秒杀

    1. Zookeeper简述 我们要了解一样技术,首先应该要到它的官网,因为官网的信息一般都是最准确的,如下图是Zookeeper官网对它的介绍. 从官网的介绍中,可以总结出,Zookeeper是一个 ...

  5. 【Zookeeper】源码之序列化

    一.前言 在完成了前面的理论学习后,现在可以从源码角度来解析Zookeeper的细节,首先笔者想从序列化入手,因为在网络通信.数据存储中都用到了序列化,下面开始分析. 二.序列化 序列化主要在zook ...

  6. 【Zookeeper】源码分析之持久化--FileTxnLog

    一.前言 前一篇已经分析了序列化,这篇接着分析Zookeeper的持久化过程源码,持久化对于数据的存储至关重要,下面进行详细分析. 二.持久化总体框架 持久化的类主要在包org.apache.zook ...

  7. 【Zookeeper】源码分析之持久化--FileTxnSnapLog

    一.前言 前面分析了FileSnap,接着继续分析FileTxnSnapLog源码,其封装了TxnLog和SnapShot,其在持久化过程中是一个帮助类. 二.FileTxnSnapLog源码分析 2 ...

  8. 【Zookeeper】源码分析之Watcher机制(一)

    一.前言 前面已经分析了Zookeeper持久话相关的类,下面接着分析Zookeeper中的Watcher机制所涉及到的类. 二.总体框图 对于Watcher机制而言,主要涉及的类主要如下. 说明: ...

  9. 【Zookeeper】源码分析之Watcher机制(二)

    一.前言 前面已经分析了Watcher机制中的第一部分,即在org.apache.zookeeper下的相关类,接着来分析org.apache.zookeeper.server下的WatchManag ...

  10. 【Zookeeper】源码分析之Watcher机制(三)之Zookeeper

    一.前言 前面已经分析了Watcher机制中的大多数类,本篇对于ZKWatchManager的外部类Zookeeper进行分析. 二.Zookeeper源码分析 2.1 类的内部类 Zookeeper ...

随机推荐

  1. 算法金 | 再见,PCA 主成分分析!

    ​大侠幸会,在下全网同名[算法金] 0 基础转 AI 上岸,多个算法赛 Top [日更万日,让更多人享受智能乐趣] 1. 概念:数据降维的数学方法 定义 主成分分析(PCA)是一种统计方法,通过正交变 ...

  2. 【Java】JVM字节码分析

    一.功能 1.工作原理 2.解释和运行 jvm本质上是运行在计算机上的程序,负责运行java字节码文件 对字节码文件中的指令,实时的解释成机器码,供计算机执行 3.内存管理 自动为对象.方法等分配内存 ...

  3. 代码审计——基础(JAVASE)

    JAVASE 目录 JAVASE 基本语法 关键字 变量 作业1 作业完成 第一题:简单的介绍了java语言历史,优势.发展 第二题:特性:面向对象.跨平台.封装.继承.多态.抽象.扩展性.健壮性.垃 ...

  4. jquery中封装了三种ajax请求方式

          // jQuery中封装了3种 ajax 请求方式         // 1, get请求方式         // 2, post请求方式         // 3, 综合请求方式    ...

  5. 告别Word,用Python打造你的专业简历!

    今天给大家介绍下一个在纯 python 中构建简历的实用工具,工具的连接地址https://github.com/koek67/resume-builder/blob/main/readme.md 用 ...

  6. ETL工具-nifi干货系列 第十四讲 nifi处理器QueryDatabaseTableRecord查询表数据实战教程

    1.处理器QueryDatabaseTableRecord和处理器QueryDatabaseTable比较相似,该组件生成一个 SQL 查询,或者使用用户提供的语句,并执行它以获取所有在指定的最大值列 ...

  7. LNMP集群架构

    网站集群拆分 上一节我们是部署了单机的LNMP,再往下,要进行拆分了,无论是性能.还是安全性,都务必要拆分. 拆分的内容有 nginx集群 mysql nfs共享存储 等 拆分思路 情况1 当前的单机 ...

  8. 网易面试:SpringBoot如何开启虚拟线程?

    虚拟线程(Virtual Thread)也称协程或纤程,是一种轻量级的线程实现,与传统的线程以及操作系统级别的线程(也称为平台线程)相比,它的创建开销更小.资源利用率更高,是 Java 并发编程领域的 ...

  9. 在AS中logcat的设置过滤信息图文教程

    [当前使用版本 1.4] logcat是调试代码的很好工具,但是因为跳出的信息过多让人目不暇接,未必能让人找到想要的信息,所以我们必须从中过滤出想要的信息 [样例]这里我们要搜索 System.out ...

  10. mysql多表删除指定记录

    在Mysql4.0之后,mysql开始支持跨表delete. Mysql可以在一个sql语句中同时删除多表记录,也可以根据多个表之间的关系来删除某一个表中的记录. 假定我们有两张表:Product表和 ...