springboot如何整合zookeeper和对zookeeper节点的简单操作
- 发表于:2023-03-12 17:39
- 阅读(41)
ZooKeeper
(1)ZooKeeper 介绍、安装和配置
zookeeper官网地址:https://zookeeper.apache.org。
安装和配置请自行百度。
(2)ZooKeeper 的简单示例
这里直接通过单元测试,来简单展示如果创建节点,监听节点状态改变,以及删除节点。
1、在 pom.xml 中添加依赖:
<!-- 整合zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.8.1</version>
</dependency>
2、编写单元测试代码:
package com.example.demo;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@SpringBootTest
class ZookeeperLockDemoApplicationTests {
// 配置连接ZooKeeper服务端地址
private final String connectString = "127.0.0.1:2181";
// 过期时间默认3秒
private final int sessionTimeout = 3000;
// 定义ZooKeeper连接对象
private ZooKeeper zooKeeper;
/**
* 初始化ZooKeeper连接对象
*/
//@Test
//@Before
@BeforeEach
public void contextLoads() {
try {
zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
// 监听并处理连接对象的状态改变事件
try {
// 获取所有子节点列表
List<String> children = zooKeeper.getChildren("/", true);
// 遍历输出各个子节点
children.forEach(node -> {
// 打印输出节点信息
System.out.println(node);
});
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} catch (IOException e) {
System.out.println("创建新的ZooKeeper连接失败!");
e.printStackTrace();
}
}
/**
* 测试创建节点
* <p>
* 注意:如果节点已存在,则会报异常:org.apache.zookeeper.KeeperException$NodeExistsException: KeeperErrorCode = NodeExists for /testNode
* 无法再创建新的同名子节点
*/
@Test
public void testCreateNode() throws KeeperException, InterruptedException {
// 定义节点名称
String nodeName = "/testNode";
// 定义节点值,节点存储的数据
byte[] nodeData = new String("测试的节点数据").getBytes();
// 节点的权限
ArrayList<ACL> openAclUnsafe = ZooDefs.Ids.OPEN_ACL_UNSAFE;
// 节点的类型:持久有序、持久无序、临时有序、临时无序
CreateMode persistent = CreateMode.PERSISTENT;
zooKeeper.create(nodeName, nodeData, openAclUnsafe, persistent);
}
/**
* 监听节点状态
*/
@Test
public void watchNodeStatus() {
// 通过死循环持续监听zookeeper节点状态改变,节点状态改变的时候会执行初始化方法中定义的监听处理逻辑
// 每一次节点的改变都会输出所有节点列表
while (true) {
try {
System.out.println("正在监听节点状态 ...");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 判断节点是否已存在
*/
@Test
public void testNodeExist() throws KeeperException, InterruptedException {
Stat exists = zooKeeper.exists("/testNode", false);
// 如果不为空,表示节点已存在,会输出:/testNode 节点已存在
System.out.println(Objects.nonNull(exists) ? "/testNode 节点已存在" : "/testNode 节点不存在");
}
/**
* 测试删除节点
*/
@Test
public void testDeleteNode() throws KeeperException, InterruptedException {
zooKeeper.delete("/testNode", 0);
}
}
3、初始化zookeeper连接对象
在调用各个单元测试方法之前,我们需要先创建一个zookeeper连接对象,我是通过 @BeforeEach
注解在调用各个方法之前进行初始化,然后编写了监听节点状态更改需要执行的业务逻辑,如果状态改变(新增/修改/删除了节点),则执行如下代码打印输出当前的子节点列表:
@Override
public void process(WatchedEvent event) {
// 监听并处理连接对象的状态改变事件
try {
// 获取所有子节点列表
List<String> children = zooKeeper.getChildren("/", true);
// 遍历输出各个子节点
children.forEach(node -> {
// 打印输出节点信息
System.out.println(node);
});
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
4、新建节点
执行 testCreateNode 方法创建子节点,我们可以在终端通过zookeeper客户端查看当前的子节点列表。
/**
* 测试创建节点
* <p>
* 注意:如果节点已存在,则会报异常:org.apache.zookeeper.KeeperException$NodeExistsException: KeeperErrorCode = NodeExists for /testNode
* 无法再创建新的同名子节点
*/
@Test
public void testCreateNode() throws KeeperException, InterruptedException {
// 定义节点名称
String nodeName = "/testNode";
// 定义节点值,节点存储的数据
byte[] nodeData = new String("测试的节点数据").getBytes();
// 节点的权限
ArrayList<ACL> openAclUnsafe = ZooDefs.Ids.OPEN_ACL_UNSAFE;
// 节点的类型:持久有序、持久无序、临时有序、临时无序
CreateMode persistent = CreateMode.PERSISTENT;
zooKeeper.create(nodeName, nodeData, openAclUnsafe, persistent);
}
在终端使用命令:
# 进入客户端
zkCli.sh
# 查看当前/下面所有子节点
ls /
注意:如果存在同名节点,也就是节点已存在,再创建的时候就会报错。
5、监听节点状态改变
执行 watchNodeStatus 方法,通过死循环持续监听节点状态的改变,如果状态改变,就会自动执行初始化zookeeper连接对象中定义的监听业务逻辑。
/**
* 监听节点状态
*/
@Test
public void watchNodeStatus() {
// 通过死循环持续监听zookeeper节点状态改变,节点状态改变的时候会执行初始化方法中定义的监听处理逻辑
// 每一次节点的改变都会输出所有节点列表
while (true) {
try {
System.out.println("正在监听节点状态 ...");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我们可以在终端下通过zookeeper客户端直接使用命令创建和删除节点,看看zookeeper会不会自动执行我们定义的监听业务逻辑代码,在终端执行如下命令:
# 创建节点
create /tempNode
# 删除节点
delete /tempNode
可以看到控制台输出的日志,分析日志我们可以看到我们定义的监听业务逻辑代码每次在节点状态更改之后都会自动执行。
6、判断节点是否存在
/**
* 判断节点是否已存在
*/
@Test
public void testNodeExist() throws KeeperException, InterruptedException {
Stat exists = zooKeeper.exists("/testNode", false);
// 如果不为空,表示节点已存在,会输出:/testNode 节点已存在
System.out.println(Objects.nonNull(exists) ? "/testNode 节点已存在" : "/testNode 节点不存在");
}
7、删除节点
/**
* 测试删除节点
*/
@Test
public void testDeleteNode() throws KeeperException, InterruptedException {
zooKeeper.delete("/testNode", 0);
}
执行完删除方法之后,我们可以到终端进入zookeeper客户端通过命令查看是否已删除,我这边看到是删除成功了。
还是使用命令:
ls /
OK!有关在springboot对zookeeper的简单操作示例就展示到此为止,更多用法请参考官网或其他博客。
上一篇:springboot整合rabbitmq实现消息队列
下一篇:没有了
相关推荐
-
mac安装subversion,并使用svn命令检出服务器上的代码库项目
mac安装svn只要通过Homebrew安装即可,不需要下载额外的安装包手动安装,Homebrew类似一个软件库,我们可以通过brew命令实现一键下载并安装我们所需要的常用软件。
-
Java如何获取泛型类T的Class
我们平时在封装接口或抽象类的时候经常会用到Java的泛型,经常会在传入一个泛型类T,然后封装一些抽象的方法,泛型的好处就是在编译的时候检查类型安全,并且所有的强制类型转换都是隐式和自动的,这样可以提高代码的通用性。但是我们有时候需要获取泛型类的Class,那可以如何获取到呢?
-
springboot项目事务报错:Transaction synchronization is not active
这几天在使用spring声明式事务的时候突然报了一个错误:Transaction synchronization is not active,之前使用的都是好好的,为什么这次就不行了呢?不就是加一个 @Transactional 而已嘛???
-
mysql应该如何在where语句中添加if语句进行条件判断?where if 语句应该如何使用
我们在平时的项目开发中,有时候会遇到复杂一点的需求,需要我们手动编写复杂的SQL语句,并且有时候需要根据每条表记录的实际情况进行判断,根据每条记录动态添加不同的where条件,这个时候我们就可以在where语句中使用if语句进行条件判断,那么where if应该如何正确使用呢?
-
关于websocket多节点分布式问题的解决方案
websocket是一种在单个TCP连接上进行双全工通信的协议,使用websocket,我们可以实现服务端主动向各个订阅消息通道的客户端推送消息。这点比传统的http轮询请求要更好一点,避免一些无用的请求,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
-
mac如何把文件压缩成tar、zip以及如何解压tar、zip?
有时候我们需要把文件压缩成一个tar文件或zip文件,发送给别人,那么在macos系统应该如何压缩和解压缩呢?
-
openjdk和jdk有什么区别,应该如何选择?
我们一开始学习java的时候,安装的都是从sun官网或oracle官网下载的jdk安装包,但其实还有另外一个来源可以获取到jdk安装包,那就是openjdk,它和jdk基本一样,推荐使用openjdk。
-
如果git仓库发生变更,IDEA如何直接修改git远程仓库地址?
有时候我们整理远程仓库代码的时候,会修改远程仓库的名称,或者所属分组,这个时候在IDEA由于还是使用原先拉取的旧仓库地址,导致本地代码会提交不了,也更新不了远程最新代码,那么这个时候要如何修改IDEA当前的git远程仓库地址呢?如何无缝修改,修改完之后就能和原来一样更新提交,并且以前的提交记录也保留呢?
-
微信公众号自定义菜单报错:no permission to use weapp in menu rid:xxxxxxx
昨晚公司系统添加微信公众号菜单突然报错:{"errcode":45064,"errmsg":"no permission to use weapp in menu rid: 60311f70-0736ff08-29143906"}
-
Java如何使用stream流对List列表数据进行自定义排序
我们一般做排序功能都是通过在mysql数据库中的表中定义好排序字段,然后使用升序或降序来进行排序,复杂一点的话就配合多个排序字段进行排序,但是如果碰到那种无法使用表的字段进行排序的情况,我们需要先从数据库中取出列表数据,然后再通过业务代码对列表进行排序,这个时候我们就可以使用redis或Java的stream流。
-
微信企业付款到零钱报错:此请求可能存在风险,已被微信拦截
具体错误信息:com.github.binarywang.wxpay.exception.WxPayException: 返回代码:[SUCCESS],返回信息:[支付失败],结果代码:[FAIL],错误代码:[NO_AUTH],错误详情:[此请求可能存在风险,已被微信拦截。]
-
springboot项目使用@Transactional注解如何避免长事务问题
在springboot项目中,我们开启事务是非常简单的,使用注解的方式就是在需要开启事务的方法上添加@Transactional,这样就可以实现这个方法里面的所有操作和调用方法的操作都绑定在一个事务上面,要么全部一起执行成功,要么全部一起执行失败,如果其中有某个地方抛了异常,则整个方法涉及的事务操作都会回滚,但是如果随意滥用@Transactional,又有可能引发长事务问题,导致数据库死锁、数据库连接池占满等问题。
-
css实现“展开阅读全文”功能
最近发现很多博客网站,资讯网站喜欢把资讯博文,内容等这些大文本的信息在页面显示的时候都会有个“展开阅读全文”的按钮,点击这个按钮即可展开显示所有的内容,不然一开始就显示那么长的篇幅相对来说既不美观,又对用户体验不好。现在就让我来仿照这类网站实现一个“展开阅读全文”功能。这里主要用到的前端技术是html+jquery+css,只做展开功能,没做收起功能(收起功能没必要吧,谁会去收起呀???)。
-
关于编程中面向对象的理解,什么是面向对象
面向对象设计相对于结构化程序设计可以说是一种更优秀的程序设计方法。它的基本思想是使用类、对象、继承、封装、消息等基本概念进行程序设计。它是从现实世界中客观存在的事物(即对象)出发来构造软件系统,并在软件系统构造中尽可能运用人类的自然思维方式,强调直接以现实世界中的事物(即对象)为中心来思考,认识问题。
-
我的linux操作命令总结,记录常用linux操作命令
平常本地开发项目使用的系统基本都是window系统,而且都是图形化操作,非常方便,window也是越做越好了,项目部署到生产环境一般都是选择linux系统(当然window server系列也可以),而linux一般则选择centOS居多,这里记录一下linux常用命令,以免老是过几天就忘了,后续不断补充。