Java操作Zookeeper原理及过程详解

网友投稿 539 2022-12-06


Java操作Zookeeper原理及过程详解

ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。

Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心。 服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据。如下图所示,在 Dubbo架构中 Zookeeper 就担任了注册中心这一角色。

maven依赖

org.apache.zookeeper

zookeeper

3.6.0

程序其它依赖:

org.apache.logging.log4j

log4j-core

2.11.2

org.apache.logging.log4j

log4j-core

2.11.2

org.apache.logging.log4j

log4j-1.2-api

2.11.2

org.apache.logging.log4j

log4j-slf4j-impl

2.11.2

org.apache.zookeeper

zookeeper

3.6.0

org.slf4j

slf4j-log4j12

API操作代码:

package com.zhi.test;

import java.util.List;

import org.apache.logging.log4j.LogManager;

import org.apache.logging.log4j.Logger;

import org.apache.zookeeper.CreateMode;

import org.apache.zookeeper.WatchedEvent;

import org.apache.zookeeper.Watcher;

import org.apache.zookeeper.ZooDefs.Ids;

import org.apache.zookeeper.ZooKeeper;

import org.apache.zookeeper.data.Stat;

import org.junit.jupiter.api.AfterAll;

import org.junit.jupiter.api.BeforeAll;

import org.junit.jupiter.api.MethodOrderer;

import org.junit.jupiter.api.Order;

import org.junit.jupiter.api.Test;

import org.junit.jupiter.api.TestInstance;

import org.junit.jupiter.api.TestInstance.Lifecycle;

import org.junit.jupiter.api.TestMethodOrder;

/**

* Zookeeper操作测试

*

* @author 张远志

* @since 2020年5月3日14:31:28

*

*/

@TestInstance(Lifecycle.PER_CLASS)

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)

public class ZookeeperTest {

private final Logger logger = LogManager.getLogger(this.getClass());

private ZooKeeper zooKeeper;

private final String path = "/test";

@BeforeAll

public void init() throws Exception {

zooKeeper = new ZooKeeper("192.168.59.131:2181", 60000, new Watcher() {

public void process(WatchedEvent event) {

logger.info("事件类型:{},路径:{}", event.getType(), event.getPath());

}

});

}

/**

* 添加数据,当路径已经存在时会报错,初始版本号为0。第三个参数是权限控制。

* 第四个参数,CreateMode:

*

*

*

*

*

*

*

*/

@Order(1)

@Test

public void create() {

try {

String back = zooKeeper.create(path, "这是一个测试".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

logger.info("添加一条数据成功,实际路径:{}", back);

} catch (Exception e) {

logger.error("调用create出错", e);

}

}

/**

* 判断路径是否存在,不存在时返回null

*/

@Order(2)

@Test

public void exists() {

try {

Stat stat = zooKeeper.exists(path, false);

logger.info("路径为{}的节点{}存在", path, stat == null ? "不" : "");

} catch (Exception e) {

logger.error("调用exists出错", e);

}

}

/**

* 查询数据,路径不存在时会报错

*/

@Order(3)

@Test

public void find() {

try {

byte[] bits = zooKeeper.getData(path, false, new Stat()); // 路径不存在时会报错

String data = new String(bits);

logger.info("路径{}查询到数据:{}", path, data);

} catch (Exception e) {

logger.error("调用getData出错", e);

}

}

/**

* 获取子目录,结果为空时返回一个长度为0的ArrayList

*/

@Order(3)

@Test

public void children() {

try {

List list = zooKeeper.getChildren(path, false);

logger.info("路径{}的子目录有:{}", path, String.join("、", list.toArray(new String[0])));

} catch (Exception e) {

logger.error("调用getChildren出错", e);

}

}

/**

* 修改数据,路径不存在时会报错,版本号与存储中不一致时也报错

*/

@Order(4)

@Test

public void udpate() {

try {

Stat stat = zooKeeper.exists(path, false);

if (stat != null) {

stat = zooKeeper.setData(path, "这是一个修改测试".getBytes(), stat.getVersion()); // 版本号为-1时不做版本校验

logger.info("数据修改成功,原版本号:{},新版本号:{}", stat.getAversion(), stat.getVersion());

}

} catch (Exception e) {

logger.error("调用setData出错", e);

}

}

/**

* 删除节点,路http://径不存在时报错,版本号不一致时也会报错

*/

@Order(5)

@Test

public void delete() {

try {

zooKeeper.delete(path, -1); // -1表示不做版本校验

logger.info("根据path删除数据成功");

} catch (Exception e) {

logger.error("调用delete出错", e);

}

}

@AfterAll

public void destory() throws Exception {

if (zooKeeper != null) {

zooKeeper.close();

}

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:eclipse导入工程报错问题项目或者文件有红叉的解决方案
下一篇:java编写简易贪吃蛇游戏
相关文章

 发表评论

暂时没有评论,来抢沙发吧~