当前位置: 代码迷 >> 综合 >> ZooKeeper Java 客户端连接— Curator
  详细解决方案

ZooKeeper Java 客户端连接— Curator

热度:57   发布时间:2024-01-29 08:24:01.0

除了ZkClient客户端之外,还有一个用的比较多的ZooKeeper客户端 curator,它是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等等,相对于ZkClient它表现的更为强大。

Maven依赖引入

Curator也是对ZooKeeper的封装,相对于ZkClient,它表现的更为强大,也是Spring Cloud集成ZooKeeper所使用的客户端,如下为curator的Maven引入:

<dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>2.12.0</version>
</dependency>
<dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>2.12.0</version>
</dependency>

Curator连接ZooKeeper

Curator提供了两种方式连接Zookeeper服务器,一种是通过静态工厂方法连接,另一种是通过fluent代码形式构建Zookeeper连接,推荐使用该方法。代码如下所示:

public static CuratorFramework getFramework() {if(framework == null) {synchronized (CuratorFramework.class) {if(framework == null) {//重试策略RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);//工厂构建CuratorFramework client = CuratorFrameworkFactory.builder()//设置Zookeeper服务地址端口.connectString(host).sessionTimeoutMs(5000)  // 会话超时时间.connectionTimeoutMs(5000) // 连接超时时间.retryPolicy(retryPolicy) //设置重试策略.build();client.start(); //启动客户端}}}return framework;
}
//另一种创建代码如下所示,不推荐使用该方法
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient("host",5000, 5000, retryPolicy);

Curator CURD API:

Curator全部使用fluent风格进行编程,分别提供了create()、setData()、getData()、getChildren()、delete()方法创建、修改、获取删除节点,都使用forPath()方法传入节点。代码如下所示:

CuratorFramework framework = CuratorFrameworkClient.getFramework();
//创建阶段
framework.create().creatingParentContainersIfNeeded() //如果必须创建父节点.withMode(CreateMode.PERSISTENT) //节点类型.withACL(null) //权限.forPath("/createNode/node"); //节点
//修改节点数据
framework.setData() //修改节点.forPath("/createNode/node", "node1".getBytes());
//获取节点数据
framework.getData().forPath("/createNode");
//获取子节点
framework.getChildren().forPath("/createNode");
//删除节点
framework.delete().deletingChildrenIfNeeded() //如果必须删除子节点.forPath("/createNode");

如上代码所示,相对于ZkClient代码更为清晰,也更为方便,除了上面展示的常用方法外,还有更多方法可以参考文档。

Curator 监听节点变化

相对于ZkClient的监听器,Curator的监听模式更为强大,不仅可以监听节点,可以监听子节点的变化,还能监听子节点的值的变化。Curator是采用cache的模式对节点进行监听的,如下代码分别是Curator的三种监听方式,

//监听节点变化,只能监听节点数据变化,不能监听子节点变化
public static void listenerNode() throws Exception {CuratorFramework framework = CuratorFrameworkClient.getFramework();ExecutorService pool = Executors.newCachedThreadPool();//使用的是NodeCache,创建NodeCache实例,并且传入客户端与,要接听的节点final NodeCache nodeCache = new NodeCache(framework, "/test", false);nodeCache.getListenable().addListener(new NodeCacheListener() {public void nodeChanged() throws Exception {//节点数据发生变化,调用该方法,可以通过NodeCache实例获取变化的节点与数据System.out.println("path : " + nodeCache.getCurrentData().getPath());System.out.println("data : " + new String(nodeCache.getCurrentData().getData()));System.out.println("stat : " + nodeCache.getCurrentData().getStat());System.out.println();}});nodeCache.start();
}
//监听子节点的变化,只能监听一级子节点,并不能监听子节点下的节点
public static void listenerChildren() throws Exception {CuratorFramework framework = CuratorFrameworkClient.getFramework();ExecutorService pool = Executors.newCachedThreadPool();//创建子节点Cache实例,并且传入父节点,监听传入节点的子节点final PathChildrenCache pathChildrenCache = new PathChildrenCache(framework, "/test", false);pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {ChildData data = pathChildrenCacheEvent.getData();System.out.println(pathChildrenCacheEvent.getType());switch (pathChildrenCacheEvent.getType()) {//子节点添加case CHILD_ADDED:System.out.println("CHILD_ADDED : " + data.getPath() + "  数据:" + data.getData());break;//子节点删除case CHILD_REMOVED:System.out.println("CHILD_REMOVED : " + data.getPath() + "  数据:" + data.getData());break;//子节点更新case CHILD_UPDATED:System.out.println("CHILD_UPDATED : " + data.getPath() + "  数据:" + data.getData());break;default:break;}}});pathChildrenCache.start();
}
//可以接听节点,子节点。以及子节点下的节点的变化。
public static void listenerTreeChildren() throws Exception {CuratorFramework framework = CuratorFrameworkClient.getFramework();ExecutorService pool = Executors.newCachedThreadPool();//创建TreeCache 并传入要监听的节点final TreeCache treeCache = new TreeCache(framework, "/test");treeCache.getListenable().addListener(new TreeCacheListener() {public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {ChildData data = treeCacheEvent.getData();if (data != null) {switch (treeCacheEvent.getType()) {//节点添加case NODE_ADDED:System.out.println("NODE_ADDED : " + data.getPath() + "  数据:" + new String(data.getData()));break;//节点删除case NODE_REMOVED:System.out.println("NODE_REMOVED : " + data.getPath() + "  数据:" + new String(data.getData()));break;//节点更改case NODE_UPDATED:System.out.println("NODE_UPDATED : " + data.getPath() + "  数据:" + new String(data.getData()));break;default:break;}} else {System.out.println("data is null : " + treeCacheEvent.getType());}}});
}