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-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操作代码:
packagecom.zhi.test;
importjava.util.List;
importorg.apache.logging.log4j.LogManager;
importorg.apache.logging.log4j.Logger;
importorg.apache.zookeeper.CreateMode;
importorg.apache.zookeeper.WatchedEvent;
importorg.apache.zookeeper.Watcher;
importorg.apache.zookeeper.ZooDefs.Ids;
importorg.apache.zookeeper.ZooKeeper;
importorg.apache.zookeeper.data.Stat;
importorg.junit.jupiter.api.AfterAll;
importorg.junit.jupiter.api.BeforeAll;
importorg.junit.jupiter.api.MethodOrderer;
importorg.junit.jupiter.api.Order;
importorg.junit.jupiter.api.Test;
importorg.junit.jupiter.api.TestInstance;
importorg.junit.jupiter.api.TestInstance.Lifecycle;
importorg.junit.jupiter.api.TestMethodOrder;
/**
*Zookeeper操作测试
*
*@author张远志
*@since2020年5月3日14:31:28
*
*/
@TestInstance(Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
publicclassZookeeperTest{
privatefinalLoggerlogger=LogManager.getLogger(this.getClass());
privateZooKeeperzooKeeper;
privatefinalStringpath="/test";
@BeforeAll
publicvoidinit()throwsException{
zooKeeper=newZooKeeper("192.168.59.131:2181",60000,newWatcher(){
publicvoidprocess(WatchedEventevent){
logger.info("事件类型:{},路径:{}",event.getType(),event.getPath());
}
});
}
/**
*添加数据,当路径已经存在时会报错,初始版本号为0。第三个参数是权限控制。
*第四个参数,CreateMode:
*PERSISTENT:持久化保存
*PERSISTENT_SEQUENTIAL:持久化保存,并且路径附加一个自动增长的序号
*EPHEMERAL:临时数据,客户端断开连接时自动删除数据(dubbo就是采用这种机制)
*EPHEMERAL_SEQUENTIAL:客户端断开连接时自动删除数据,并且路径会附加一个自动增长的序号
*CONTAINER:
*PERSISTENT_WITH_TTL:客户端断开连接时自动删除数据,当节点在指定时间没有被修改且没有子目录时,数据会被删除
*PERSISTENT_SEQUENTIAL_WITH_TTL:客户端断开连接时自动删除数据,路径会附加一个自动增长的序号,且当节点在指定时间没有被修改且没有子目录时,数据会被删除
*/
@Order(1)
@Test
publicvoidcreate(){
try{
Stringback=zooKeeper.create(path,"这是一个测试".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
logger.info("添加一条数据成功,实际路径:{}",back);
}catch(Exceptione){
logger.error("调用create出错",e);
}
}
/**
*判断路径是否存在,不存在时返回null
*/
@Order(2)
@Test
publicvoidexists(){
try{
Statstat=zooKeeper.exists(path,false);
logger.info("路径为{}的节点{}存在",path,stat==null?"不":"");
}catch(Exceptione){
logger.error("调用exists出错",e);
}
}
/**
*查询数据,路径不存在时会报错
*/
@Order(3)
@Test
publicvoidfind(){
try{
byte[]bits=zooKeeper.getData(path,false,newStat());//路径不存在时会报错
Stringdata=newString(bits);
logger.info("路径{}查询到数据:{}",path,data);
}catch(Exceptione){
logger.error("调用getData出错",e);
}
}
/**
*获取子目录,结果为空时返回一个长度为0的ArrayList
*/
@Order(3)
@Test
publicvoidchildren(){
try{
Listlist=zooKeeper.getChildren(path,false);
logger.info("路径{}的子目录有:{}",path,String.join("、",list.toArray(newString[0])));
}catch(Exceptione){
logger.error("调用getChildren出错",e);
}
}
/**
*修改数据,路径不存在时会报错,版本号与存储中不一致时也报错
*/
@Order(4)
@Test
publicvoidudpate(){
try{
Statstat=zooKeeper.exists(path,false);
if(stat!=null){
stat=zooKeeper.setData(path,"这是一个修改测试".getBytes(),stat.getVersion());//版本号为-1时不做版本校验
logger.info("数据修改成功,原版本号:{},新版本号:{}",stat.getAversion(),stat.getVersion());
}
}catch(Exceptione){
logger.error("调用setData出错",e);
}
}
/**
*删除节点,路径不存在时报错,版本号不一致时也会报错
*/
@Order(5)
@Test
publicvoiddelete(){
try{
zooKeeper.delete(path,-1);//-1表示不做版本校验
logger.info("根据path删除数据成功");
}catch(Exceptione){
logger.error("调用delete出错",e);
}
}
@AfterAll
publicvoiddestory()throwsException{
if(zooKeeper!=null){
zooKeeper.close();
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。