1 Curator API
CuratorFramework 是Netflix公司开发一款连接zookeeper服务的框架,提供了比较全面的功能,除了基础的节点的操作,节点的监听,还有集群的连接以及重试。
1.1 导入curator相关包
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.10.0</version>
</dependency>
1.2 导入springboot基础包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</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>
1.2 配置CuratorFramework客户端
package zookeeper.zk;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ZookeeperConfig {
@Value("${zookeeper.url}")
private String zkUrl;
@Bean
public CuratorFramework getCuratorFramework() {
/**
* 同步创建zk实例,原生api是异步的
*
* curator链接zookeeper的策略:ExponentialBackoffRetry
* baseSleepTimeMs: 初始sleep的时间
* maxRetries: 最大重试次数
* maxSleepMs: 最大重试时间
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
/**
* curator链接zookeeper的策略:RetryNTimes
* n: 重试次数
* sleepMsBetweenRetries: 每次重试间隔的时间
*/
// RetryPolicy retryPolicya = new RetryNTimes(3, 5000);
/**
* curator链接zookeeper的策略: RetryOneTime
* sleepMsBetweenRetry: 每次重试间隔的时间
* 只重试一次 不推荐
*/
// RetryPolicy retryPolicyab = new RetryOneTime(3000);
/**
* 永远重试,不推荐使用
*/
// RetryPolicy retryPolicyac = new RetryForever(12);
/**
* curator链接zookeeper的策略: RetryUntilElapsed
* maxElapsedTimeMs:最大重试时间
* sleepMsBetweenRetries: 每次重试间隔
* 重试时间超过maxElapsedTimeMs后,就不再重试
*/
// RetryPolicy retryPolicyad = new RetryUntilElapsed(2000, 3000);
CuratorFramework client = CuratorFrameworkFactory
.builder()
//登录用户List也可以 .authorization("digest", "ripper:123456".getBytes())
.connectString(zkUrl)
//会话时间必须大于心跳时间,不然会报错的
.sessionTimeoutMs(20000)
.retryPolicy(retryPolicy)
//namespace表示站点-工作空间-客户端的名字-根节点
.namespace("workspace")
.build();
client.start();
return client;
}
}
yml文件相关
zookeeper:
url: xxxxxxxxx,xxxxxxx //单机或者集群(逗号隔开)
1.3 curator API
1.3.1 创建节点
package zookeeper.test;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class CuratorTest {
@Autowired
private CuratorFramework curatorFramework;
/**
* 创建节点类型,可自行尝试
*/
@Test
public void addnode() {
try {
//节点路径
String nodePath = "/ripper/addnode";
//节点数据
byte[] data = "format".getBytes();
curatorFramework.create().creatingParentsIfNeeded()
// PERSISTENT普通节点 PERSISTENT_SEQUENTIAL顺序节点EPHEMERAL临时节点 EPHEMERAL_SEQUENTIAL临时顺序节点
.withMode(CreateMode.PERSISTENT)
//ACL后面会涉及
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
//定义节点名称和节点数据
.forPath(nodePath, data);
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.3.2 删除节点
@Test
public void deletenode() {
try {
String nodePath = "/super/imooc";
curatorFramework.delete()
.guaranteed() //如果删除失败,后端还是会继续删除,直到成功
.deletingChildrenIfNeeded() //如果有子节点就删除
.withVersion(2) //根据版本号删除子节点
.forPath(nodePath);
} catch (Exception e) {
e.printStackTrace();
}
}
1.3.3 修改节点
@Test
public void updatenode() {
try {
String nodePath = "/ripper/updatenode";
byte[] data = "format".getBytes();
curatorFramework.setData()
.withVersion(2)
.forPath(nodePath, data);
} catch (Exception e) {
e.printStackTrace();
}
}
1.3.4 查询节点
@Test
public void querynode() {
try {
// 节点数据对象
Stat stat = new Stat();
String nodePath = "/ripper/querynode";
byte[] bytes = curatorFramework.getData()
.storingStatIn(stat)
.forPath(nodePath);
} catch (Exception e) {
e.printStackTrace();
}
}
1.3.5 监听(只会执行一次)
@Test
public void watcher() {
try {
String nodePath = "/ripper/watcher";
curatorFramework.getData()
//watcher只会触发一次,一次性的
.usingWatcher(new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("监听触发");
}
}).forPath(nodePath);
Thread.sleep(100000);
} catch (Exception e) {
e.printStackTrace();
}
}
1.3.6 监听(永久生效)
nodeCache:对一个节点进行监听,监听事件包括指定的路径节点的增、删、改的操作。
@Test
public void watcherforever() {
try {
String nodePath = "/ripper/watcherforever1";
//删除节点的时候,nodeCache为null,空指针异常
final NodeCache nodeCache = new NodeCache(curatorFramework, nodePath);
//true 初始化的时候,获取node的值 并缓存
nodeCache.start(true);
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("监听成功");
}
});
Thread.sleep(100000);
} catch (Exception e) {
e.printStackTrace();
}
}
1.3.7 监听(永久生效)
PathChildrenCache: 对指定的路径节点的一级子目录进行监听,不对该节点的操作进行监听,对其子目录的节点进行增、删、改的操作监听
TreeCache: 可以将指定的路径节点作为根节点(祖先节点),对其所有的子节点操作进行监听,呈现树形目录的监听,可以设置监听深度,最大监听深度为2147483647(int类型的最大值)。
@Test
public void watcherchildenforever() {
try {
String nodePath = "/ripper/watcherchildenforever";
//删除节点的时候,nodeCache为null,空指针异常
final PathChildrenCache nodeCache = new PathChildrenCache(curatorFramework, nodePath, true);
//BUILD_INITIAL_CACHE 同步 其他两种是异步
nodeCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
nodeCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
if(pathChildrenCacheEvent.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)){
System.out.println("初始化成功");
} else if(pathChildrenCacheEvent.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){
System.out.println("添加节点");
} else if(pathChildrenCacheEvent.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
System.out.println("子节点数据更改");
} else if(pathChildrenCacheEvent.getType().equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){
System.out.println("子节点被删除");
}
}
});
Thread.sleep(100000);
} catch (Exception e) {
e.printStackTrace();
}
}
1.3.8 ACL
@Test
public void acl() {
try {
String nodePath = "/ripper/acl";
List<ACL> list = new ArrayList<>();
Id ripper1 = new Id("digest", "ripper1:123456");
Id ripper2 = new Id("digest", "ripper2:123456");
list.add(new ACL(ZooDefs.Perms.ALL, ripper1));
list.add(new ACL(ZooDefs.Perms.DELETE | ZooDefs.Perms.READ, ripper2));
curatorFramework.setACL().withACL(list).forPath(nodePath);
} catch (Exception e) {
e.printStackTrace();
}
}