Zookeeper学习-day2-Java 客户端 API的使用

春节假期过去了,收收心我们来开始继续学习Zookeeper的其他相关知识.今天要说的是 Zookeeper Java客户端API的使用

在切入正题之前,延着上节内容我们来说几个客户端的脚本(客户端连接,创建,读取,更新,删除)

  • 客户端连接
$ sh zkCli.sh
image.png

看到末尾是
WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0]
就表示连接成功了

上面这种方式就是直接连,连接本地的Zookeeper.
那么要连接指定地址

$ sh zkCli.sh -server ip:port
  • 创建

creat

创建节点,其中 -s 或 -e 分别指定特性: 顺序或者临时节点,默认不添加-s , -e. 创建的是持久节点

create [-s] [-e] path data acl

[zk: 192.168.131.134:2181(CONNECTED) 0] create /zk-test 123
Created /zk-test

其中参数的含义,
/zk-test 为节点的path, 123 为数据data, 最后一个参数是acl策略,缺省情况下,不做任何权限的控制,详细的说明后面继续

  • 读取

ls

使用ls命令, 可以查看指定节点下的所有第一级的所有子节点

ls path [watch]

path 表示的是指定数据节点的节点路径

image.png
ls /

第一次部署集群,默认在根节点 "/" 下面又一个叫/zookeeper的保留节点

image.png

get

get path [watch]
image.png

其中

  • czxid. 节点创建时的zxid.

  • mzxid. 节点最新一次更新发生时的zxid.

  • ctime. 节点创建时的时间戳.

  • mtime. 节点最新一次更新发生时的时间戳.

  • dataVersion. 节点数据的更新次数.

  • cversion. 其子节点的更新次数.

  • aclVersion. 节点ACL(授权信息)的更新次数.

  • ephemeralOwner. 如果该节点为ephemeral节点, ephemeralOwner值表示与该节点绑定的session id. 如果该节点不是ephemeral节点, ephemeralOwner值为0. 至于什么是ephemeral节点, 请看后面的讲述.

  • dataLength. 节点数据的字节数.

  • numChildren. 子节点个数.

  • 更新

set

set path data [version]
image.png

执行完上面的命令后,会发现dataversion的值由原来的 0 变成 1.关于ZNode版本的知识后面我再深入浅出

  • 删除

delete

delete path [version]

image.png
image.png

由以上两个示例应该很容易理解为什么删除失败的原因了吧,

刚刚简单的介绍了下命令行的增删改查,
这里不多说了.下面我们进入主要的内容也就是标题上的 Java客户端API的使用
主要要讲的有下面几点

  • 创建会话
  • 创建节点
  • 删除节点
  • 读取数据
  • 更新数据
  • 检测节点是否存在
  • 权限控制

zookeeper常用的四个字命令

ZooKeeper 支持某些特定的四字命令字母与其的交互。它们大多是查询命令,用来获取 ZooKeeper 服务的当前状态及相关信息。用户在客户端可以通过 telnet 或 nc 向 ZooKeeper 提交相应的命令

  1. 可以通过命令:echo stat|nc 127.0.0.1 2181 来查看哪个节点被选择作为follower或者leader
  2. 使用echo ruok|nc 127.0.0.1 2181 测试是否启动了该Server,若回复imok表示已经启动。
  3. echo dump| nc 127.0.0.1 2181 ,列出未经处理的会话和临时节点。
  4. echo kill | nc 127.0.0.1 2181 ,关掉server
  5. echo conf | nc 127.0.0.1 2181 ,输出相关服务配置的详细信息。
  6. echo cons | nc 127.0.0.1 2181 ,列出所有连接到服务器的客户端的完全的连接 / 会话的详细信息。
  7. echo envi |nc 127.0.0.1 2181 ,输出关于服务环境的详细信息(区别于 conf 命令)。
  8. echo reqs | nc 127.0.0.1 2181 ,列出未经处理的请求。
  9. echo wchs | nc 127.0.0.1 2181 ,列出服务器 watch 的详细信息。
  10. echo wchc | nc 127.0.0.1 2181 ,通过 session 列出服务器 watch 的详细信息,它的输出是一个与 watch 相关的会话的列表。
  11. echo wchp | nc 127.0.0.1 2181 ,通过路径列出服务器 watch 的详细信息。它输出一个与 session 相关的路径。

创建会话

创建一个客户端Zookeeper(org.apache.zookeeper.ZooKeeper)示例,来连接服务器

image.png

参数的详细解释一定要看官方的说明,为了方便我把几处说明复制到了一起,看起了方便很多

   /**
     * @param connectString
     *            comma separated host:port pairs, each corresponding to a zk
     *            server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" If
     *            the optional chroot suffix is used the example would look
     *            like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a"
     *            where the client would be rooted at "/app/a" and all paths
     *            would be relative to this root - ie getting/setting/etc...
     *            "/foo/bar" would result in operations being run on
     *            "/app/a/foo/bar" (from the server perspective).
     * @param sessionTimeout
     *            session timeout in milliseconds
     * @param watcher
     *            a watcher object which will be notified of state changes, may
     *            also be notified for node events
     * @param canBeReadOnly
     *            (added in 3.4) whether the created client is allowed to go to
     *            read-only mode in case of partitioning. Read-only mode
     *            basically means that if the client can't find any majority
     *            servers but there's partitioned server it could reach, it
     *            connects to one in read-only mode, i.e. read requests are
     *            allowed while write requests are not. It continues seeking for
     *            majority in the background.
     * @param sessionId
     *            specific session id to use if reconnecting
     * @param sessionPasswd
     *            password for this session
     */

ZookeeperDemo.java
创建一个最基本的Zookeeper的会话实例

import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;

public class ZookeeperDemo {
    private static Logger logger = LoggerFactory.getLogger(ZookeeperDemo.class);
    //同步工具类
    private static CountDownLatch latch = new CountDownLatch(1);
    public static void main(String[] args) {
        try {
            //实例Zookeeper
            ZooKeeper zooKeeper = new ZooKeeper("192.168.131.134:2181", 3000,new MyWatcher(latch));

            logger.info("zooKeeper: [{}]" , zooKeeper);
            latch.await();

            Thread.sleep(2000);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

MyWatcher.java

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import java.util.concurrent.CountDownLatch;

public class MyWatcher implements Watcher {
    private CountDownLatch latch;
    public MyWatcher(CountDownLatch latch) {
        this.latch=latch;
    }

    @Override
    public void process(WatchedEvent event) {
        if (Event.KeeperState.SyncConnected == event.getState()){
            System.out.println(event);
            latch.countDown();
        }
    }
}

在源码中有这么一段代码是KeepState的描述,从字面就可以理解其含义

public static KeeperState fromInt(int intValue) {
    switch(intValue) {
        case   -1: return KeeperState.Unknown;
        case    0: return KeeperState.Disconnected;
        case    1: return KeeperState.NoSyncConnected;
        case    3: return KeeperState.SyncConnected;
        case    4: return KeeperState.AuthFailed;
        case    5: return KeeperState.ConnectedReadOnly;
        case    6: return KeeperState.SaslAuthenticated;
        case -112: return KeeperState.Expired;
        default:
            throw new RuntimeException("Invalid integer value for conversion to KeeperState");
    }
}

我们在构造函数的注释中发现Zookeeper的构造方法允许传入sessionIdsessionPasswd.其目的是为了复用会话,以维持之前会话的有效性.下面的例子就是复用sessionIdsessionPasswd来创建一个Zookeeper对象实例

public static void main(String[] args) {
        try {
            ZooKeeper zooKeeper1 = new ZooKeeper("192.168.131.134:2181", 3000,new MyWatcher(latch));
            logger.info("zooKeeper 1:[{}]" , zooKeeper1);
            latch.await();
            long sessionId = zooKeeper1.getSessionId();
            byte[] passwd = zooKeeper1.getSessionPasswd();
            logger.info("zooKeeper=> sessionId:[{}], passwd:[{}]" , sessionId, new String(passwd));


            ZooKeeper zooKeeper2 = new ZooKeeper("192.168.131.134:2181", 3000,new MyWatcher2(latch1),sessionId,passwd);
            logger.info("zooKeeper 2:[{}]" , zooKeeper2);
            Thread.sleep(2000);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
image.png

创建节点

两个节点创建分别以同步和异步的方式来创建节点

image.png

    /**
     * @param path
     *                the path for the node
     * @param data
     *                the initial data for the node
     * @param acl
     *                the acl for the node
     * @param createMode
     *                specifying whether the node to be created is ephemeral
     *                and/or sequential
     * @param cb
     *                回调函数
     * @param ctx
     *                用于传递一个对象的上下文,在回调方法执行的时候使用(通常放一个上下文(Context)信息)
     */

ZookeeperDemo.java
同步接口创建节点

public class ZookeeperDemo {
    private static Logger logger = LoggerFactory.getLogger(ZookeeperDemo.class);
    private static CountDownLatch latch = new CountDownLatch(1);
    public static void main(String[] args) {
        try {
            ZooKeeper zooKeeper = new ZooKeeper("192.168.131.134:2181", 3000,new MyWatcher(latch));
            latch.await();
            //同步创建
            String path1 = zooKeeper.create("/zk-test-e-",          //path
                                            "".getBytes(),          //data
                                            Ids.OPEN_ACL_UNSAFE,    //acl
                                            CreateMode.EPHEMERAL);  //createMode
            logger.info("path 1: [{}]" , path1);

            String path2 = zooKeeper.create("/zk-test-e-child","".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            logger.info("path 2: [{}]" , path2);

            Thread.sleep(2000);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        }
    }
}
image.png

ZookeeperDemo.java
异步接口创建节点

public class ZookeeperDemo {
    private static Logger logger = LoggerFactory.getLogger(ZookeeperDemo.class);
    private static CountDownLatch latch = new CountDownLatch(1);
    public static void main(String[] args) {
        try {
            ZooKeeper zooKeeper = new ZooKeeper("192.168.131.134:2181", 3000,new MyWatcher(latch));
            latch.await();

            //异步创建
            zooKeeper.create("/zk-test-e-",          //path
                             "".getBytes(),          //data
                             Ids.OPEN_ACL_UNSAFE,    //acl
                             CreateMode.EPHEMERAL,   //createMode
                             new MyStringCallback(), //callback
                             "I am Context");        //Context

            zooKeeper.create("/zk-test-e-child", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, new MyStringCallback(), "I am Context");

            Thread.sleep(2000);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

import org.apache.zookeeper.AsyncCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 异步回调函数实现类
 */
public class MyStringCallback implements AsyncCallback.StringCallback {
    private static Logger logger = LoggerFactory.getLogger(MyStringCallback.class);
    @Override
    public void processResult(int rc, String path, Object ctx, String name) {
        logger.info("Create path result:[{}] path:[{}] ctx:[{}] name:[{}]", rc,  path,  ctx,  name);
    }
}
image.png

在CreateMode 的源码中的这段信息

  • 持久(PERSISTENT)
  • 持久顺序(PERSISTENT_SEQUENTIAL)
  • 临时(EPHEMERAL)
  • 临时顺序(EPHEMERAL_SEQUENTIAL )
/**
     * The znode will not be automatically deleted upon client's disconnect.
     */
    PERSISTENT (0, false, false),
    /**
    * The znode will not be automatically deleted upon client's disconnect,
    * and its name will be appended with a monotonically increasing number.
    */
    PERSISTENT_SEQUENTIAL (2, false, true),
    /**
     * The znode will be deleted upon the client's disconnect.
     */
    EPHEMERAL (1, true, false),
    /**
     * The znode will be deleted upon the client's disconnect, and its name
     * will be appended with a monotonically increasing number.
     */
    EPHEMERAL_SEQUENTIAL (3, true, true);

创建节点的回调函数包含了七种不同的回调接口.所有我们要在不同的异步接口中实现不同的接口

  • StatCallback
  • DataCallback
  • ACLCallback
  • ChildrenCallback
  • Children2Callback
  • StringCallback
  • VoidCallback

回调函数方法参数说明

processResult(int rc, String path, Object ctx, String name)
参数 说明
rc Result Code, 服务器响应码
[0] :调用成功
[-4] 客户端和服务端连接断开
[-110] 指定节点已存在
[-112] 会话已经过期
path 接口调用时传入API的数据节点的节点路径参数值
ctx 接口调用时传入API的ctx参数值
name 实际在服务端创建的节点名

删除节点

删除节点Zookeeper API 提供了2个接口,如图


image.png

参数的含义

   /**
     * @param path
     *                the path of the node to be deleted.
     * @param version
     *                the expected node version.
     * @param cb
     *                回调函数
     * @param ctx
     *                用于传递一个对象的上下文,在回调方法执行的时候使用(通常放一个上下文(Context)信息)
     */

先来查看下我们现有服务器上的节点,删除标红的节点


image.png
public class ZookeeperDeleteNode {
    private static CountDownLatch latch = new CountDownLatch(1);
    private static CountDownLatch latch1 = new CountDownLatch(1);
    public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        ZooKeeper zooKeeper = new ZooKeeper("192.168.131.134:2181", 3000,new MyWatcher(latch));
        latch.await();

        zooKeeper.delete("/zk-test-e-child",
                        0,
                        new MyVoidCallback(latch1),
                        "I am Context");
        latch1.await();
    }
}
public class MyVoidCallback implements AsyncCallback.VoidCallback {
    private static Logger logger = LoggerFactory.getLogger(MyVoidCallback.class);

    private CountDownLatch latch;
    public MyVoidCallback(CountDownLatch latch){
        this.latch = latch;
    }

    @Override
    public void processResult(int rc, String path, Object ctx) {
        logger.info("delete path result:[{}] path:[{}] ctx:[{}] ", rc,  path,  ctx);
        latch.countDown();
    }
}

删除成功

image.png

删除失败

已经删除过了.


image.png

读取数据

读取节点Zookeeper API 提供了8个接口,如图


image.png
   /**
     * @param path
     * @param watcher explicit watcher
     * @param watch whether need to watch this node
     * @param cb a handler for the callback
     * @param ctx context to be provided to the callback
     * @param stat stat of the znode designated by path
     */

持续更新中.......(未完待续)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容

  • 一、ZooKeeper的背景 1.1 认识ZooKeeper ZooKeeper---译名为“动物园管理员”。动物...
    algernoon阅读 9,058评论 1 106
  • [TOC] Zookeeper客户端Curator使用详解 前提 维护多个博客比较麻烦,简书和博客园放弃维护,后续...
    zhrowable阅读 85,891评论 23 116
  • ZooKeeper是Hadoop Ecosystem中非常重要的组件,它的主要功能是为分布式系统提供一致性协调(C...
    把爱放下会走更远阅读 21,700评论 1 18
  • 今天去姑姑家里,捞鱼,摘瓜,摘柿子,hao白菜,砸核桃,啃骨头,吃鱼。特别丰富,特别开心。 发现地里有瓜,自己摘了...
    大雨不愁阅读 310评论 0 0
  • 必须要保持镇定,知道自己现在最需要做的事情是什么,知道最需要提高的能力是什么,其实自己要是有高三那样的拼劲还怕什么...
    考拉1阅读 121评论 0 0