zookeeper JavaAPI操作


提示:以下是本篇文章正文内容

一、Curator介绍

  • Curator是Apache ZooKeeper的Java客户端库
  • 常见的ZooKeeper Java API:
    原生Java API
    ZkClient
    Curator
  • Curator项目的目标是简化ZooKeeper客户端的使用。
  • Curator官网

二、Curator API常用操作

1、增删改查API操作

public class CuratorTest {
    private CuratorFramework client;
    @Before
    public void testConnect() {
        /*// 第一种方式
        // 四个参数:连接字符串(zkServer地址和端口)、会话超时时间,单位ms
        // 连接超时时间,单位ms、重试策略(连接没有建立成功以后重试的模式)

        // 第一个参数为每两次重试间隔的时间,单位为ms,第二个参数为最大重试次数
        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(3000, 10);
        // 中间两个参数不给的话有默认值,默认值就是我们给出的这个
        CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", 60 * 1000,
                15 * 1000, retryPolicy);
        // 开启连接
        client.start();*/

        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(3000, 10);
        // 第二种方式(链式编程)
        // nameSpace命名空间,默认以后将“zkTest”作为根节点
        client = CuratorFrameworkFactory.builder().connectString("localhost:2181").sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).retryPolicy(retryPolicy).namespace("zkTest").build();
        // 开启连接
        client.start();
    }

    /**
     * 创建节点:create 持久 临时 顺序 数据
     * 将命令行操作还原成代码
     * 1、基本创建
     * 2、创建节点 带有数据
     * 3、设置节点的类型
     * 4、创建多级节点
     */
    @Test
    public void testCreate1() throws Exception {
        // 1、基本创建
        // 如果创建节点,没有指定数据,则默认将当前客户端的ip作为数据存储
        java.lang.String path = client.create().forPath("/app1");
        System.out.println(path);
    }

    @Test
    public void testCreate2() throws Exception {
        // 2、创建节点 带有数据
        java.lang.String path = client.create().forPath("/app2", "hehe".getBytes());
        System.out.println(path);
    }

    @Test
    public void testCreate3() throws Exception {
        // 3、设置节点的类型
        // 默认类型:持久化
        // 创建临时节点,当前会话结束,节点就会被删除
        java.lang.String path = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3", "hehe".getBytes());
        System.out.println(path);
    }
    @Test
    public void testCreate4() throws Exception {
        // 4、创建多级节点
        // creatingParentsIfNeeded():如果父节点不存在,则创建父节点
        java.lang.String path = client.create().creatingParentsIfNeeded().forPath("/app4/p1");
        System.out.println(path);
    }
    // ----------------------------------------------------------------------------------------------------------

    /**
     * 查询节点
     * 查询数据
     * 查询子节点
     * 查询节点状态信息: ls -s
     */
    @Test
    public void testGet1() throws Exception {
        byte[] data = client.getData().forPath("/app1");
        System.out.println(new String(data));
    }

    @Test
    public void testGet2() throws Exception {
        List<String> list = client.getChildren().forPath("/");
        System.out.println(list);
    }

    @Test
    public void testGet3() throws Exception {
        Stat status = new Stat();
        client.getData().storingStatIn(status).forPath("/app1");
        System.out.println(status);
    }
    // ----------------------------------------------------------------------------------------------------------

    /**
     * 修改数据
     * 根据版本修改
     * @throws Exception
     */
    @Test
    public void testSet() throws Exception {
        client.setData().forPath("/app1", "hello".getBytes());
    }

    @Test
    public void testSetForVersion() throws Exception {
        Stat status = new Stat();
        client.getData().storingStatIn(status).forPath("/app1");
        int version = status.getVersion();
        System.out.println(version);
        client.setData().withVersion(version).forPath("/app1", "haha".getBytes());
    }
// ----------------------------------------------------------------------------------------------------------
    @Test
    public void testDelete() throws Exception {
        client.delete().forPath("/app1");
    }
    @Test
    public void testDelete2() throws Exception {
        // 删除带有子节点的节点
        client.delete().deletingChildrenIfNeeded().forPath("/app4");
    }

    @Test
    public void testDelete3() throws Exception {
        // 必须成功的删除
        client.delete().guaranteed().forPath("/app2");
    }
    @Test
    public void testDelete4() throws Exception {
        // 回调
        client.delete().guaranteed().inBackground(new BackgroundCallback() {
            @Override
            public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                System.out.println("我被删除了");
                System.out.println(curatorEvent);
            }
        }).forPath("/app1");
    }



    @After
    public void close() {
        if(client != null) {
            client.close();
        }
    }
}

-测试工程中的POM文件需要添加以下依赖:

<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>

        <!--curator-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.0</version>
        </dependency>
        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

2、watch事件监听

  • zookeeper允许用户在指定节点上注册一些watcher,并且在一些特定事件触发的时候,zookeeper服务端会将事件通知到感兴趣的客户端上去,该机制是zookeeper实现分布式协调服务的重要特性。
  • 引入了watch机制实现了发布/订阅功能,能够让多个订阅者同时监听某一个对象,当一个对象自身状态变化时,会通知所有订阅者。
  • 原生支持通过注册watcher来进行事件监听,但是其使用并不是特别方便需要开发人员自己反复注册watcher,比较繁琐。
  • curator引入了Cache来实现对zookeeper服务端事件的监听。
  • 提供了三种Watcher
    NodeCache:只是监听某一个特定的节点。
    PathChildrenCache:监控一个ZNode的子节点。
    TreeChe:可以监听整个树上的所有节点,类似于PathChildrenChe和NodeCache的组合。
  • 下面是具体的演示过程:
package org.example.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.xml.soap.Node;
import java.util.List;

public class CuratorWatcherTest {
    private CuratorFramework client;
    @Before
    public void testConnect() {
        /*// 第一种方式
        // 四个参数:连接字符串(zkServer地址和端口)、会话超时时间,单位ms
        // 连接超时时间,单位ms、重试策略(连接没有建立成功以后重试的模式)

        // 第一个参数为每两次重试间隔的时间,单位为ms,第二个参数为最大重试次数
        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(3000, 10);
        // 中间两个参数不给的话有默认值,默认值就是我们给出的这个
        CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", 60 * 1000,
                15 * 1000, retryPolicy);
        // 开启连接
        client.start();*/

        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(3000, 10);
        // 第二种方式(链式编程)
        // nameSpace命名空间,默认以后将“zkTest”作为根节点
        client = CuratorFrameworkFactory.builder().connectString("localhost:2181").sessionTimeoutMs(60 * 1000).
                connectionTimeoutMs(15 * 1000).retryPolicy(retryPolicy).namespace("zkTest").build();
        // 开启连接
        client.start();
    }

    /**
     * 演示NodeChe:给指定一个节点注册监听器
     */

    @Test
    public void testNodeChe() throws Exception {
        // 1、创建NodeCache对象 jdk版本是不用加final的
        final NodeCache nodeCache = new NodeCache(client, "/app4");
        // 2、注册监听
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                System.out.println("节点变化了……");
                //获取修改节点后的数据
                byte[] data = nodeCache.getCurrentData().getData();
                System.out.println(new String(data));

            }
        });
        nodeCache.start();
        // 使方法一直执行,如果是真实场景,不用这么写,因为用的是线程
        while(true) {

        }

    }

    /**
     * 演示PathChildrenCache:监听某个节点的所有子节点们
     * 但是感知不到当前节点的变化
     */
    @Test
    public void testPathChildrenCache() throws Exception {
        // 1、创建监听对象
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/app2", true);
        // 2、绑定监听器
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
                System.out.println("子节点变化了……");
                System.out.println(pathChildrenCacheEvent);
                // 监听子节点的数据变更,拿到变更后的数据
                // 获取类型
                PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();
                // 判断类型是否是update
                if(type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)) {
                    System.out.println("数据变了");
                    byte[] data = pathChildrenCacheEvent.getData().getData();
                    System.out.println(new String(data));
                }
            }
        });
        pathChildrenCache.start();
        while (true) {

        }
     }

    /**
     * 演示PtestTreeCache:监听某个节点的所有子节点们和自己
     */
    @Test
    public void testTreeCache() throws Exception {
        // 创建监听器
        TreeCache treeCache = new TreeCache(client, "/app2");
        // 注册监听
        treeCache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
                System.out.println("节点变化了");
                System.out.println(treeCacheEvent);
            }
        });
        treeCache.start();
        while (true) {

        }

    }

    @After
    public void close() {
        if(client != null) {
            client.close();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值