Zookeeper客户端Curator Framework使用

Curator是Zookeeper开源的客户端框架,封装了很多API,使用起来非常的方便,直接进入正题,讲解如何使用。

一、客户端创建

使用静态工厂方式进行创建,connectionInfo为Zookeeper地址,例如:127.0.0.1:2181

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);

CuratorFramework client = CuratorFrameworkFactory.newClient(connectionInfo, retryPolicy);

client.start();

二、CuratorFramework常用API

方法名 描述
create() 开始创建操作, 可以调用额外的方法(比如方式mode 或者后台执行background) 并在最后调用forPath()指定要操作的ZNode
delete() 开始删除操作. 可以调用额外的方法(版本或者后台处理version or background)并在最后调用forPath()指定要操作的ZNode
checkExists() 开始检查ZNode是否存在的操作. 可以调用额外的方法(监控或者后台处理)并在最后调用forPath()指定要操作的ZNode
getData()

开始获得ZNode节点数据的操作. 可以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 

并在最后调用forPath()指定要操作的ZNode

setData() 开始设置ZNode节点数据的操作. 可以调用额外的方法(版本或者后台处理) 并在最后调用forPath()指定要操作的ZNode
getChildren()

开始获得ZNode的子节点列表。 以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 

并在最后调用forPath()指定要操作的ZNode

inTransaction() 开始是原子ZooKeeper事务. 可以复合create, setData, check, and/or delete 等操作然后调用commit()作为一个原子操作提交

对上述接口进行了二次封装,写了个ZKClient工具类

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.transaction.CuratorTransaction;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

/**
 * Created by wzj on 2018/5/4.
 */
public class ZKClient
{
    /**
     * 客户端
     */
    private CuratorFramework client = null;

    /**
     * 构造方法
     *
     * @param connectionInfo zk主机
     */
    public ZKClient(String connectionInfo)
    {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);

        client = CuratorFrameworkFactory.newClient(connectionInfo, retryPolicy);

        client.start();
    }

    /**
     * 创建节点
     *
     * @param path       路径
     * @param createMode 节点类型
     * @param data       节点数据
     * @return 是否创建成功
     */
    public boolean crateNode(String path, CreateMode createMode, String data)
    {
        try
        {
            client.create().withMode(createMode).forPath(path, data.getBytes());
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * 删除节点
     *
     * @param path 路径
     * @return 删除结果
     */
    public boolean deleteNode(String path)
    {
        try
        {
            client.delete().forPath(path);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * 删除一个节点,并且递归删除其所有的子节点
     *
     * @param path 路径
     * @return 删除结果
     */
    public boolean deleteChildrenIfNeededNode(String path)
    {
        try
        {
            client.delete().deletingChildrenIfNeeded().forPath(path);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * 判断节点是否存在
     *
     * @param path 路径
     * @return true-存在  false-不存在
     */
    public boolean isExistNode(String path)
    {
        try
        {
            Stat stat = client.checkExists().forPath(path);

            return stat != null ? true : false;
        }
        catch (Exception e)
        {
            e.printStackTrace();

            return false;
        }
    }

    /**
     * 判断节点是否是持久化节点
     * @param path 路径
     * @return 2-节点不存在  | 1-是持久化 | 0-临时节点
     */
    public int isPersistentNode(String path)
    {
        try
        {
            Stat stat = client.checkExists().forPath(path);

            if (stat == null)
            {
                return 2;
            }

            if (stat.getEphemeralOwner() > 0)
            {
                return 1;
            }

            return 0;
        }
        catch (Exception e)
        {
            e.printStackTrace();

            return 2;
        }
    }

    /**
     * 获取节点数据
     *
     * @param path 路径
     * @return 节点数据,如果出现异常,返回null
     */
    public String getNodeData(String path)
    {

        try
        {
            byte[] bytes = client.getData().forPath(path);
            return new String(bytes);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 注册节点数据变化事件
     *
     * @param path              节点路径
     * @param nodeCacheListener 监听事件
     * @return 注册结果
     */
    public boolean registerWatcherNodeChanged(String path, NodeCacheListener nodeCacheListener)
    {
        NodeCache nodeCache = new NodeCache(client, path, false);
        try
        {
            nodeCache.getListenable().addListener(nodeCacheListener);

            nodeCache.start(true);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }


    /**
     * 更新节点数据
     *
     * @param path     路径
     * @param newValue 新的值
     * @return 更新结果
     */
    public boolean updateNodeData(String path, String newValue)
    {
        //判断节点是否存在
        if (!isExistNode(path))
        {
            return false;
        }

        try
        {
            client.setData().forPath(path, newValue.getBytes());
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * 开启事务
     *
     * @return 返回当前事务
     */
    public CuratorTransaction startTransaction()
    {
        return client.inTransaction();
    }
}

三、事务处理

增删改查每一个节点都是一个原子操作,一系列的原子操作就是一个事务。

在ZKClient增加获取事务方法

public CuratorTransaction startTransaction()
    {
        return client.inTransaction();
    }

测试,构造三个原子操作

zkClient.startTransaction().create().forPath("/henan")
                .and().create().forPath("/henan/zhengzhou")
                .and().delete().forPath("/ads")
                .and().commit();

只有三个原子操作都成功,三个操作才能最终执行。

四、注册节点监听

将Zookeeper作为配置中心的时候,最常用的是监听节点数据的变动。

在ZKClient添加注册节点变动方法。

    /**
     * 注册节点数据变化事件
     *
     * @param path              节点路径
     * @param nodeCacheListener 监听事件
     * @return 注册结果
     */
    public boolean registerWatcherNodeChanged(String path, NodeCacheListener nodeCacheListener)
    {
        NodeCache nodeCache = new NodeCache(client, path, false);
        try
        {
            nodeCache.getListenable().addListener(nodeCacheListener);

            nodeCache.start(true);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }

测试监听/zhejiang节点数据变动

        zkClient.registerWatcherNodeChanged("/zhejiang", new NodeCacheListener()
        {
            @Override
            public void nodeChanged() throws Exception
            {
                System.out.println("/zhejiang node data changeed,new data is = " + zkClient.getNodeData("/zhejiang"));
            }
        });

        zkClient.updateNodeData("/zhejiang","hahah change1");
Demo代码下载链接: https://download.csdn.net/download/u010889616/10394855







你可能感兴趣的:(Zookeeper,Zookeeper,Curator)