文章目录
一、节点信息
前提:centos102、centos103、centos104 服务器都已经开启
pom.xml 依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
log4j.properties 配置
# 设置全局的日志记录级别为 INFO
log4j.rootLogger=INFO, stdout
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
# 文件输出
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
1、创建节点
zkClient.java 代码
// 注意:逗号后面不能有空格
private String connectString = "centos102:2181,centos103:2181,centos104:2181";
private int sessionTimeout = 2000;
private ZooKeeper zkClient;
// 创建客户端
@Before
public void init() throws IOException {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
}
});
}
// 创建子节点
@Test
public void create() throws InterruptedException, KeeperException {
String nodeCreated = zkClient.create("/frost", "cat".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
运行创建子节点,看看是否创建了该节点
2、获取子节点并监听节点变化
@Test
public void getChildren() throws InterruptedException, KeeperException {
List<String> children = zkClient.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
}
那如果此时我再创建一个节点,此时控制台没有任何变化,我想要创建一个节点控制台能够看到相关变化怎么办?此时只需要将程序保持不结束,然后将客户端查看子节点函数放入监听器中。
3、判断节点是否存在
@Test
public void exit() throws InterruptedException, KeeperException {
Stat stat = zkClient.exists("/frost", false);
System.out.println(stat == null ? "not exits" : "exits");
}
4、客户端向服务端写入数据
写入请求直接发给 Leader 节点
- 客户端发送写入请求,leader节点执行写入操作
- leader通知follow1执行写入操作
- folllow1写入完毕给leader返回确认ack
- 现在半数以上服务器完成写入,leader给客户端发送确认ack
- leader通知follow2写入
- follow2写入完毕给leader发送确认ack
写入请求直接发给 follow 节点
- 客户端发送写入请求,
- follow1 将写入请求发送给leader
- leader节点执行写入操作,然后leader通知follow1执行写入操作
- folllow1写入完毕给leader返回确认ack
- 现在半数以上服务器完成写入,leader给follow1发送确认ack
- follow1给客户端发送确认ack
- leader通知follow2写入
- follow2写入完毕给leader发送确认ack
二、服务器动态上下线监听
1、监听过程
以下红色字体写错,应该是下线则通知注册监听器的客户端
对于ZooKeeper集群来说,客户端和服务器都相当于客户端,区别在于:服务器在ZooKeeper集群中是创建节点,客户端在ZooKeeper是监听信息。
2、代码
服务器注册到zk集群
import org.apache.zookeeper.*;
import java.io.IOException;
public class DistributeServer {
private String connectString = "centos102:2181,centos103:2181,centos104:2181";
private int sessionTimeout = 2000;
ZooKeeper zk;
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
DistributeServer server = new DistributeServer();
// 1. 获取zk连接
server.getConnect();
// 2. 注册服务器到 zk 集群
server.regist(args[0]);
// 3. 启动业务逻辑(睡觉)
server.business();
}
private void business() throws InterruptedException {
Thread.sleep(Long.MAX_VALUE);
}
private void regist(String hostname) throws InterruptedExceptio