zookeeper 客户端 zkCli 命令详解

      • 安装 zookeeper
      • 启动/停止 zookeeper
      • 配置文件
      • zookeeper 命令
      • zookeeper cli
      • 对 znode 进行增删改查
        • 创建节点 create
        • 列出节点 ls
        • 获取节点信息 get
        • 检查状态 stat
        • 修改节点 set
        • 删除节点 rmr
        • 删除节点 delete
      • 其他指令
        • 历史记录 history
        • 重复之前的命令 redo
        • 是否输出 watch 事件(printwatches)
        • 关闭连接 close
        • 打开连接 connect
        • 退出连接 quit
        • 强制同步 sync
      • ACL 操作
        • ACL Permissions
        • 权限相关命令
        • ACL Schemes
          • world 方案
          • IP 方案
          • auth 方案
          • digest 方案
        • 创建节点时指定 ACL
      • zookeeper quota

安装 zookeeper

brew install zookeeper

启动/停止 zookeeper

brew services start zookeeper

brew services stop zookeeper

配置文件

配置文件位置:/usr/local/etc/zookeeper/

下面是配置文件的内容:

tickTime=2000 
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5

dataDir=/usr/local/var/run/zookeeper/data

clientPort=2181

tickTime 是zookeeper中的基本时间单元,单位是毫秒。

datadir是zookeeper持久化数据存放的目录。

clientPort是zookeeper监听客户端连接的端口,默认是2181

initLimit:follower连接和同步leader的时长。如果大多数follower这个时长内同步失败,将重新选举一个leader代替之前的leader。如果经常发生这种情况,说明这个值设置的太低。

syncLimit:folloer同步leader的时长。如果follower在这个时长内同步失败,follower将自动重启。连接他的client将连接到其他的follower上。

zookeeper 命令

我们通过nc或者telnet命令访问2181端口,通过执行ruok(Are you OK?)命令来检查zookeeper是否启动成功:

% echo ruok | nc localhost 2181
imok

那么我看见zookeeper回答我们“I’m OK”。下表中是所有的zookeeper的命令,都是由4个字符组成。

Category Command Description
Server status ruok Prints imok if the server is running and not in an error state.
conf Prints the server configuration (from zoo.cfg).
envi Prints the server environment, including ZooKeeper version, Java version, and other system properties.
srvr Prints server statistics, including latency statistics, the number of znodes, and the server mode (standalone, leader, or follower).
stat Prints server statistics and connected clients.
srst Resets server statistics.
isro Shows whether the server is in read-only (ro) mode (due to a network partition) or read/write mode (rw).
Client connections dump Lists all the sessions and ephemeral znodes for the ensemble. You must connect to the leader (see srvr) for this command.
cons Lists connection statistics for all the server’s clients.
crst Resets connection statistics.
Watches wchs Lists summary information for the server’s watches.
wchc Lists all the server’s watches by connection. Caution: may impact server performance for a large number of watches.
wchp Lists all the server’s watches by znode path. Caution: may impact server performance for a large number of watches.
Monitoring mntr Lists server statistics in Java properties format, suitable as a source for monitoring systems such as Ganglia and Nagios.

3.5.0以上的版本会有一个内嵌的web服务,通过访问http://localhost:8080/commands来访问以上的命令列表。

zookeeper cli

使用 brew 安装,已经把 zookeeper bin 目录下的命令添加的系统中,因此在终端直接执行 zkCli,就创建了一个 zk 客户端,连接 zk 服务。

输入 help 命令(其实输入任何 zkCli 不能识别的命令,都会列出所有的命令),查看可用的命令:

zookeeper 客户端 zkCli 命令详解_第1张图片

对 znode 进行增删改查

创建节点 create

语法

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

-s 创建有序节点

如果在创建znode时,我们使用排序标志的话,ZooKeeper会在我们指定的znode名字后面增加一个数字。我们继续加入相同名字的znode时,这个数字会不断增加。这个序号的计数器是由这些排序znode的父节点来维护的。

-e 创建临时节点

znode有两种类型:ephemeral和persistent。在创建znode时,我们指定znode的类型,并且在之后不会再被修改。当创建znode的客户端的session结束后,ephemeral类型的znode将被删除。persistent类型的znode在创建以后,就与客户端没什么联系了,除非主动去删除它,否则他会一直存在。Ephemeral znode没有任何子节点。

acl 在下面的《 ACL 操作》中详细介绍。

使用方法:

普通节点

[zk: localhost:2181(CONNECTED) 3] create /mynode hello
Created /mynode
[zk: localhost:2181(CONNECTED) 4] create /mynode/subnode world
Created /mynode/subnode

有序节点

[zk: localhost:2181(CONNECTED) 4] create -s /mynode hello
Created /mynode0000000004
[zk: localhost:2181(CONNECTED) 6] create -s /mynode world
Created /mynode0000000005

临时节点

[zk: localhost:2181(CONNECTED) 7] create -e /temp hello
Created /temp

退出 zkCli,然后再重新打开它,/temp 节点已经被删除了。

列出节点 ls

语法

ls path [watch]

ls2 path [watch]

[watch] 添加一个 watch(监视器),如果该节点发生变化,watch 可以使客户端得到通知。watch 只能被触发一次。如果要一直获得znode的创建和删除的通知,那么就需要不断的在znode上开启观察模式。如果在该 path 下创建节点,会产生 NodeChildrenChanged 事件;如果在该 path 下删除节点,会产生 NodeDeleted 事件。

使用 ls2 命令来查看某个目录包含的所有文件,与 ls 不同的是它查看到time、version等信息

使用方法:

列出根节点

[zk: localhost:2181(CONNECTED) 0] ls /
[dubbo, mynode, zookeeper]
[zk: localhost:2181(CONNECTED) 1] ls2 /
[mynode, zookeeper, dubbo]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x578
cversion = 63
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 3

列出子节点

[zk: localhost:2181(CONNECTED) 2] ls /mynode
[subnode]

使用 watch

创建一个名为 1 的watch,然后再根节点下添加(删除)节点,就会触发该 watch。在其他节点下创建子节点,不会触发该 watch。

[zk: localhost:2181(CONNECTED) 3] ls / 1
[dubbo, mynode, zookeeper]
[zk: localhost:2181(CONNECTED) 4] create /mynode2 hello
Created /mynode2
WATCHER::


WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/

从上面的操作可以看到,在根节点添加了 /mynode2 节点之后,触发了 watch,WatchedEvent 的类型是 NodeChildrenChanged

获取节点信息 get

语法

get path [watch]

[watch] 添加一个 watch(监视器),如果节点内容发生改变,会产生 NodeDataChanged 事件;如果删除节点,会产生 NodeDeleted 事件。

使用方法

[zk: localhost:2181(CONNECTED) 4] get /mynode
hello
cZxid = 0x4e8
ctime = Mon Apr 02 17:25:29 CST 2018
mZxid = 0x4e8
mtime = Mon Apr 02 17:25:29 CST 2018
pZxid = 0x4e8
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

每一个对znode树的更新操作,都会被赋予一个全局唯一的ID,我们称之为zxid(ZooKeeper Transaction ID)。更新操作的ID按照发生的时间顺序升序排序。例如,z1大于z2,那么z1的操作就早于z2操作。

每个 znode 的状态信息包含以下内容:

  • czxid,创建(create)该 znode 的 zxid
  • mzxid,最后一次修改(modify)该 znode 的 zxid
  • pzxid,最后一次修改该 znode 子节点的 zxid
  • ctime,创建该 znode 的时间
  • mtime,最后一次修改该 znode 的时间
  • dataVersion,该节点内容的版本,每次修改内容,版本都会增加
  • cversion,该节点子节点的版本
  • aclVersion,该节点的 ACL 版本
  • ephemeralOwner,如果该节点是临时节点(ephemeral node),会列出该节点所在客户端的 session id;如果不是临时节点,该值为 0
  • dataLength,该节点存储的数据长度
  • numChildren,该节点子节点的个数

检查状态 stat

语法

stat path [watch]

[watch] 添加一个 watch(监视器),如果节点内容发生改变,会产生 NodeDataChanged 事件;如果删除节点,会产生 NodeDeleted 事件。

与 get 的区别是,不回列出 znode 的值。

使用方法

[zk: localhost:2181(CONNECTED) 11] stat /mynode
cZxid = 0x50e
ctime = Mon Apr 02 20:12:05 CST 2018
mZxid = 0x50e
mtime = Mon Apr 02 20:12:05 CST 2018
pZxid = 0x50e
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

修改节点 set

语法

set path data [version]

修改已经存在的节点的值

使用方法

[zk: localhost:2181(CONNECTED) 60] set /mynode newvalue
cZxid = 0x504
ctime = Mon Apr 02 18:02:56 CST 2018
mZxid = 0x505
mtime = Mon Apr 02 18:03:11 CST 2018
pZxid = 0x504
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0

可以看到,在修改节点值之后,mZxid、mtime、dataVersion 都发生了变化。

删除节点 rmr

语法

rmr path

使用方法

[zk: localhost:2181(CONNECTED) 34] rmr /mynode

删除 /mynode,不会返回任何内容。如果有子节点的时候,连带子节点也一起删除。

删除节点 delete

语法

delete path [version]

调用deleteset操作时,如果指定znode版本号,需要与当前的版本号匹配。如果版本号不匹配,操作将会失败。失败的原因可能是在我们提交之前,该znode已经被修改过了,版本号发生了增量变化。如果不指定版本号,就是直接操作最新版本的 znode。

使用方法

[zk: localhost:2181(CONNECTED) 15] create /mynode hello
Created /mynode
[zk: localhost:2181(CONNECTED) 16] delete /mynode

如果要删除的节点有子节点,不能删除

[zk: localhost:2181(CONNECTED) 33] create /mynode/sub sub
Created /mynode/sub
[zk: localhost:2181(CONNECTED) 34] delete /mynode
Node not empty: /mynode

其他指令

历史记录 history

history 列出最近的10条历史记录

[zk: localhost:2181(CONNECTED) 7] history
0 - history
1 - create /mynode hello
2 - ls /
3 - set /mynode worold
4 - get /mynode
5 - stat /mynode
6 - rmr /mynode
7 - history

重复之前的命令 redo

redo cmdno 根据 cmdno 重复之前的命令,cmdno 就是方括号里面最后的数字,每次执行命令都会自增。

[zk: localhost:2181(CONNECTED) 5] create /mynode hello
Created /mynode
[zk: localhost:2181(CONNECTED) 6] rmr /mynode
[zk: localhost:2181(CONNECTED) 7] redo 5
Created /mynode

是否输出 watch 事件(printwatches)

语法

printwatches on|off

使用方法

[zk: localhost:2181(CONNECTED) 43] printwatches
printwatches is on
[zk: localhost:2181(CONNECTED) 44] ls /mynode 1
[sub]
[zk: localhost:2181(CONNECTED) 45] create /mynode/child child

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/mynode
Created /mynode/child

如果设置 printwatches off ,就看不到上面的 WATCHER 事件了。

关闭连接 close

close

[zk: localhost:2181(CONNECTED) 50] close
[zk: localhost:2181(CLOSED) 51]
[zk: localhost:2181(CLOSED) 52] ls /
Not connected

打开连接 connect

connect host:port

[zk: localhost:2181(CLOSED) 52] connect
[zk: localhost:2181(CONNECTING) 53]
WATCHER::

WatchedEvent state:SyncConnected type:None path:null

[zk: localhost:2181(CONNECTED) 53]

指定 host:port 可以连接远程的 zk 服务。缺省的时候,会连接本地的 2181 端口。

退出连接 quit

quit

直接退出当前的 zkCli 命令行。

强制同步 sync

sync path

sync方法会强制客户端所连接的服务器状态与leader的状态同步,这样在读取 path 的值就是最新的值了。

ACL 操作

一个znode中不仅包含了存储的数据,还有 ACL(Access Control List)。znode的创建时,可以给它设置一个ACL(Access Control List),来决定谁可以对znode做哪些操作。

ACL 具有以下特点:

  1. ZooKeeper的权限控制是基于每个znode节点的,需要对每个节点设置权限
  2. 每个znode支持设置多种权限控制方案和多个权限
  3. 子节点不会继承父节点的权限,客户端无权访问某节点,但可能可以访问它的子节点
  4. 所以任何一个客户端都可以通过exists 操作来获得任何znode的状态,从而得知znode是否真的存在。

ACL Permissions

ACL 权限 ACL 简写 允许的操作
CREATE c 创建子节点
READ r 获取节点的数据和它的子节点
WRITE w 设置节点的数据
DELETE d 删除子节点 (仅下一级节点)
ADMIN a 设置 ACL 权限

权限相关命令

命令 语法 描述
getAcl getAcl path 读取ACL权限
setAcl setAcl path acl 设置ACL权限
addauth addauth scheme auth 添加认证用户
create create [-s] [-e] path data acl 创建节点时指明 ACL 权限

ACL Schemes

ZooKeeper内置了一些权限控制方案,可以用以下方案为每个节点设置权限:

方案 描述
world 只有一个用户:anyone,代表所有人(默认)
ip 使用IP地址认证
auth 使用已添加认证的用户认证
digest 使用“用户名:密码”方式认证

ACL是由鉴权方式、鉴权方式的ID和一个许可(permession)的集合组成。例如,我们想通过一个ip地址为10.0.0.1的客户端访问一个znode。那么,我们需要为znode设置一个ACL,鉴权方式使用IP鉴权方式,鉴权方式的ID为10.0.0.1,只允许读权限。那么 ACL 的格式就是:ip:10.0.0.1:w

world 方案

设置方式:setAcl world:anyone:

默认情况下时 world 方法,任何人有所有权限:

[zk: localhost:2181(CONNECTED) 6] getAcl /mynode
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 7] setAcl /mynode world:anyone:cdr
cZxid = 0x54a
ctime = Tue Apr 03 09:26:36 CST 2018
mZxid = 0x54a
mtime = Tue Apr 03 09:26:36 CST 2018
pZxid = 0x54a
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
[zk: localhost:2181(CONNECTED) 15] set /mynode hello
Authentication is not valid : /mynode

可以看出,在修改权限为 cdr 之后,不能再设置节点数据了。注意 aclVersion 也发生了变化。

IP 方案

设置方式:setAcl ip::

:可以是具体IP也可以是IP/bit格式,即IP转换为二进制,匹配前bit位,如192.168.0.0/16匹配192.168.*.*

[zk: localhost:2181(CONNECTED) 19] create /mynode hello
Created /mynode
[zk: localhost:2181(CONNECTED) 20] setAcl /mynode ip:192.168.1.250:cdrwa
cZxid = 0x552
ctime = Tue Apr 03 09:38:58 CST 2018
mZxid = 0x552
mtime = Tue Apr 03 09:38:58 CST 2018
pZxid = 0x552
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
[zk: localhost:2181(CONNECTED) 21] getAcl /mynode
'ip,'192.168.1.250
: cdrwa

使用其他电脑方法方法该节点:

#使用IP非 192.168.100.1 的机器
[zk: localhost:2181(CONNECTED) 0] get /node2
Authentication is not valid : /node2 #没有权限

[zk: localhost:2181(CONNECTED) 1] delete /node2 #删除成功(因为设置DELETE权限仅对下一级子节点有效,并不包含此节点)
auth 方案

设置方式

addauth digest : #添加认证用户
setAcl  auth::

示例:

[zk: localhost:2181(CONNECTED) 22] create /mynode1 hello
Created /mynode1
[zk: localhost:2181(CONNECTED) 23] addauth digest admin:admin #添加认证用户
[zk: localhost:2181(CONNECTED) 24] setAcl /mynode1 auth:admin:cdrwa
cZxid = 0x554
ctime = Tue Apr 03 09:44:32 CST 2018
mZxid = 0x554
mtime = Tue Apr 03 09:44:32 CST 2018
pZxid = 0x554
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
[zk: localhost:2181(CONNECTED) 25] getAcl /mynode1
'digest,'admin:x1nq8J5GOJVPY6zgzhtTtA9izLc=
: cdrwa
[zk: localhost:2181(CONNECTED) 26] get /mynode1
hello #刚才已经添加认证用户,可以直接读取数据,断开会话重连需要重新addauth添加认证用户
cZxid = 0x554
ctime = Tue Apr 03 09:44:32 CST 2018
mZxid = 0x554
mtime = Tue Apr 03 09:44:32 CST 2018
pZxid = 0x554
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
digest 方案

设置方式

setAcl  digest:::

这里的密码是经过SHA1及BASE64处理的密文,在SHELL中可以通过以下命令计算:

echo -n : | openssl dgst -binary -sha1 | openssl base64

先来算一个密文密码:

echo -n admin:admin | openssl dgst -binary -sha1 | openssl base64
x1nq8J5GOJVPY6zgzhtTtA9izLc=

示例:

[zk: localhost:2181(CONNECTED) 8] create /mynode2 hello
Created /mynode2

#使用是上面算好的密文密码添加权限:
[zk: localhost:2181(CONNECTED) 9] setAcl /mynode2 
digest:admin:x1nq8J5GOJVPY6zgzhtTtA9izLc=:cdrwa
cZxid = 0x55a
ctime = Tue Apr 03 13:17:12 CST 2018
mZxid = 0x55a
mtime = Tue Apr 03 13:17:12 CST 2018
pZxid = 0x55a
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
[zk: localhost:2181(CONNECTED) 10] getAcl /mynode2
'digest,'admin:x1nq8J5GOJVPY6zgzhtTtA9izLc=
: cdrwa

[zk: localhost:2181(CONNECTED) 11] get /mynode2
#没有权限
Authentication is not valid : /mynode2

[zk: localhost:2181(CONNECTED) 12] addauth digest admin:admin #添加认证用户
[zk: localhost:2181(CONNECTED) 13] get /mynode2
hello  #成功读取数据
cZxid = 0x55a
ctime = Tue Apr 03 13:17:12 CST 2018
mZxid = 0x55a
mtime = Tue Apr 03 13:17:12 CST 2018
pZxid = 0x55a
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

创建节点时指定 ACL

#添加 admin 用户
[zk: localhost:2181(CONNECTED) 2] addauth digest admin:admin
#创建节点时赋予权限
[zk: localhost:2181(CONNECTED) 3] create /mynode hello auth:admin:cdrwa
Created /mynode
[zk: localhost:2181(CONNECTED) 4] getAcl /mynode
'digest,'admin:x1nq8J5GOJVPY6zgzhtTtA9izLc=
: cdrwa
[zk: localhost:2181(CONNECTED) 5] close
[zk: localhost:2181(CLOSED) 6] connect
[zk: localhost:2181(CONNECTING) 7]
WATCHER::

WatchedEvent state:SyncConnected type:None path:null
#断开会话重连需要重新addauth添加认证用户
[zk: localhost:2181(CONNECTED) 7] get /mynode
Authentication is not valid : /mynode
[zk: localhost:2181(CONNECTED) 8] addauth digest admin:admin
[zk: localhost:2181(CONNECTED) 9] get /mynode
hello
cZxid = 0x56c
ctime = Tue Apr 03 15:00:27 CST 2018
mZxid = 0x56c
mtime = Tue Apr 03 15:00:27 CST 2018
pZxid = 0x56c
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

注意了!使用 rmr 删除节点没有权限时,竟然可以使用 delete

[zk: localhost:2181(CONNECTED) 25] rmr /mynode
Authentication is not valid : /mynode
[zk: localhost:2181(CONNECTED) 26] delete /mynode

zookeeper quota

zookeeper quota 机制支持节点个数(namespace)和空间大小(bytes)的设置。

zookeeper quota 保存在 /zookeeper/quota 节点下,可以设置该节点的 ACL 权限,以防其他人修改。

语法:

listquota path

setquota -n|-b val path

delquota [-n|-b] path

使用方法:

# 目前还没有任何设置
[zk: localhost:2181(CONNECTED) 9] ls /zookeeper/quota
[]
# 还没有为 /mynode 设置 quota
[zk: localhost:2181(CONNECTED) 10] listquota /mynode
absolute path is /zookeeper/quota/mynode/zookeeper_limits
quota for /mynode does not exist.
# -n表示设置znode count限制,这里表示/mynode这个path下的znode count个数限制为3(包括/mynode本身)
[zk: localhost:2181(CONNECTED) 11] setquota -n 3 /mynode
Comment: the parts are option -n val 3 path /mynode
[zk: localhost:2181(CONNECTED) 12] create /mynode/sub1 hello
Created /mynode/sub1
[zk: localhost:2181(CONNECTED) 9] listquota /mynode
absolute path is /zookeeper/quota/mynode/zookeeper_limits
Output quota for /mynode count=3,bytes=-1
Output stat for /mynode count=2,bytes=6

注意,即使节点数超出了限制,也不会看到提示信息,zookeeper 只会在日志中提醒一下。

使用 listquota 列出了节点的设置的 quota,和节点实际的容量。

[zk: localhost:2181(CONNECTED) 20] delquota -n /mynode
[zk: localhost:2181(CONNECTED) 21] listquota /mynode
absolute path is /zookeeper/quota/mynode/zookeeper_limits
Output quota for /mynode count=-1,bytes=-1
Output stat for /mynode count=2,bytes=6

删除 quota 之后,count 也变成了 -1

至此,Zookeeper客户端所有的命令介绍完毕!

参考:

  1. https://zookeeper.apache.org/doc/r3.4.11/zookeeperProgrammers.html
  2. http://www.yoonper.com/post.php?id=47
  3. http://holynull.leanote.com/post/Zookeeper
  4. https://zookeeper.apache.org/doc/r3.1.2/zookeeperQuotas.html

你可能感兴趣的:(工具使用)