通用配置
- maven依赖
<properties>
<java.version>1.8</java.version>
<skipTests>true</skipTests>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- zkclient -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.11</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
- zookeeper的集群配置 application.properties新增zk cluster的信息
# zk 集群IP地址
zookeeper.cluster.hosts=10.211.55.5:2182,10.211.55.5:2183,10.211.55.5:2184,10.211.55.5:2185
zookeeper.cluster.sessionTimeout=5000
zk原生客户端
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
/**
* zk原生客户端测试
*/
@Slf4j
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ZookeeperOriginalClientTest {
@Value("${zookeeper.cluster.hosts}")
private String hosts;
@Value("${zookeeper.cluster.sessionTimeout}")
private Integer sessionTimeout;
private ZooKeeper zk;
static class ZkOriginalWatcher implements Watcher {
@Override
public void process(WatchedEvent event) {
log.info("watched event: {}",event);
if (event.getState() == Event.KeeperState.SyncConnected){
log.info("已连接");
}
}
}
@BeforeAll
public void initZooKeeper()throws Exception{
zk = new ZooKeeper(hosts,sessionTimeout,new ZkOriginalWatcher());
log.info("init zk: {}",zk);
}
@Test
public void testNode() throws Exception{
String path = "/testnode/node2";
// 是否存在
Stat exists = zk.exists(path, true);
log.info("path stat: {}",exists);
// 创建节点
String createRet = zk.create(path, "hello,zookeeper".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
log.info("createRet: {}",createRet);
// 修改节点内容
Stat stat = zk.setData(path, "world".getBytes(), -1);
log.info("setData result: {}",stat);
// 创建多个节点
zk.create(path+"/snode1", "1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(path+"/snode2", "1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(path+"/snode3", "1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 获取所有子节点
List<String> children = zk.getChildren(path, true);
log.info("children: {}",children);
// 删除节点
zk.delete(path+"/snode3",-1);
}
}
zkClient客户端
- 支持递归创建node,递归删除节点
- session支持重连
- 创建节点数据支持序列化
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.CreateMode;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* zkClient客户端测试
*/
@Slf4j
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ZkClientTests {
@Value("${zookeeper.cluster.hosts}")
private String hosts;
private ZkClient client;
@BeforeAll
public void initClient(){
client = new ZkClient(hosts);
log.info("ZkClient已完成初始化!!!");
}
@Data
@AllArgsConstructor
static class User implements Serializable {
private String username;
private Integer age;
}
@Test
public void createTestZkClient(){
// 创建一个持久节点,值支持object
client.create("/zkclientnode2",20,CreateMode.PERSISTENT);
// 创建一个持久节点,可以递归创建节点,但无法递归设置值
client.createPersistent("/zkclientnode/users/lisi",true);
client.createPersistent("/zkclientnode/address/beijing",true);
// 创建一个持久节点,序列化
client.createPersistent("/zkclientnode/users/zhangsan",new User("张三",18));
}
@Test
public void modifyTest(){
// 读取节点内容,不存在返回Null
Object readDataBefore = client.readData("/zkclientnode2",true);
log.info("readDataBefore value: {}",readDataBefore);
// 修改节点内容
client.writeData("/zkclientnode2","wirte data");
Object readDataAfter = client.readData("/zkclientnode2",true);
log.info("readDataAfter value: {}",readDataAfter);
}
@Test
public void deleteTest(){
// 普通删除
client.delete("/zkclientnode2");
// 递归删除
client.deleteRecursive("/testnode");
// client.create("/testnode",1,CreateMode.PERSISTENT);
}
@Test
public void readTestZkClient(){
List<String> children = client.getChildren("/zkclientnode/users");
log.info("children: {}",children);
children.forEach(nodeName ->{
Object readData = client.readData("/zkclientnode/users/"+nodeName);
log.info("batch read node: {}",readData);
});
}
@Test
public void watcherTest() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
client.subscribeDataChanges("/testnode", new IZkDataListener() {
@Override
public void handleDataChange(String dataPath, Object data) throws Exception {
log.info("===========数据已发生改变! dataPath: {},data: {}==========",dataPath,data);
countDownLatch.countDown();
}
@Override
public void handleDataDeleted(String dataPath) throws Exception {
log.info("===========数据已被删除! dataPath: {}==========",dataPath);
countDownLatch.countDown();
}
});
Object readData = client.readData("/testnode");
log.info("origin data: {}",readData);
client.writeData("/testnode","899");
client.deleteRecursive("/testnode");
countDownLatch.await();
}
}