分布式服务管理框架-Zookeeper客户端zkCli.sh使用详解
原文链接:http://blog.csdn.net/xyang81/article/details/53053642
https://blog.csdn.net/dandandeshangni/article/details/80558383
在学习zookeeper(下面简称zk)客户端之前,有必要先了解一下zk的数据模型。zk维护着一个逻辑上的树形层次结构,树中的节点称为znode,和Linux系统的文件系统结构非常相似,如下图所示:
这种数据结构有如下特点:
1> 每个znode都有唯一路径标识,最顶层的znode为/,比如p_2这个znode的路径标识为/app1/p_2
,znode只支持绝对路径,不支持相对路径,也不支持“.”和“..”
2> znode可以有子节点,并且每个znode可以存储数据。但zk是被设计用来协调管理服务的,因此znode里存储的都是一些小数据,而不是大容量的数据,数据容量一般在1M范围内。
3> znode的数据有版本号,可以用在并发访问场景中,用乐观锁机制实现数据的一致性
4> znode分为临时节点和永久节点,zk的客户端和服务器通信采用长连接的方式,每个客户端和服务器通过心跳来保持连接,这个连接状态称为session,如果znode是临时节点,当session失效(即客户端与服务器断开连接),znode会被服务器自动删除。
5> znode的节点名称可以自动编号,如果app1已经存在,再创建的话,将会自动命名为app2,这种节点称为序列节点。
6> znode可以被监控,包括这个节点中存储的数据被修改、子节点列表变化(删除或新增子节点)等,一旦变化,zk服务器会通过所有监控该节点的客户端,这是zk的核心特性,zk很多的功能都是基于这个特性实现的。
基础命令操作
1、启动zk服务
./zkServer.sh start
[aaa@qq.com ~]# zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /data0/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
2、查看zk的运行状态
-
./zkServer.sh status
由于我已经配置了zk
的集群,所以此处显示状态为leader
[aaa@qq.com ~]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /data0/zookeeper/bin/../conf/zoo.cfg
Mode: leader
3、客户端链接zk
语法为:zkCli.sh -timeout 5000 -r -server ip:port
zkCli.sh
脚本是Zookeeper安装包中自带的一个客户端,放在$ZK_HOME/bin目录下,本文ZK安装在/data0/zookeeper下。
参数解释:
(1) -timeout:表示客户端向zk服务器发送心跳的时间间隔,单位为毫秒。因为zk客户端与服务器的连接状态是通过心跳检测来维护的,如果在指定的时间间隔内,zk客户端没有向服务器发送心跳包,服务器则会断开与该客户端的连接。参数5000,表示zk客户端向服务器发送心跳的间隔为5秒。
(2) -r:表示客户端以只读模式连接
(3) -server:指定zk服务器的IP与端口,zk默认的客户端端口为2181
其中参数-timeout,-r,ip:port可以省略,例如:zkCli.sh -server。
[aaa@qq.com ~]# zkCli.sh -timeout 5000 -r -server 192.168.17.64:2181
若出现下图提示所示,表示已经成功连接到服务器。
Connecting to 192.168.17.64:2181
2018-09-14 10:42:37,902 [myid:] - INFO [main:aaa@qq.com] - Client environment:zookeeper.version=3.4.12-e5259e437540f349646870ea94dc2658c4e44b3b, built on 03/27/2018 03:55 GMT
2018-09-14 10:42:37,908 [myid:] - INFO [main:aaa@qq.com] - Client environment:host.name=localhost.localdomain
2018-09-14 10:42:37,908 [myid:] - INFO [main:aaa@qq.com] - Client environment:java.version=1.8.0_171
2018-09-14 10:42:37,911 [myid:] - INFO [main:aaa@qq.com] - Client environment:java.vendor=Oracle Corporation
2018-09-14 10:42:37,911 [myid:] - INFO [main:aaa@qq.com] - Client environment:java.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.171-8.b10.el7_5.x86_64/jre
2018-09-14 10:42:37,912 [myid:] - INFO [main:aaa@qq.com] - Client environment:java.class.path=/data0/zookeeper/bin/../build/classes:/data0/zookeeper/bin/../build/lib/*.jar:/data0/zookeeper/bin/../lib/slf4j-log4j12-1.7.25.jar:/data0/zookeeper/bin/../lib/slf4j-api-1.7.25.jar:/data0/zookeeper/bin/../lib/netty-3.10.6.Final.jar:/data0/zookeeper/bin/../lib/log4j-1.2.17.jar:/data0/zookeeper/bin/../lib/jline-0.9.94.jar:/data0/zookeeper/bin/../lib/audience-annotations-0.5.0.jar:/data0/zookeeper/bin/../zookeeper-3.4.12.jar:/data0/zookeeper/bin/../src/java/lib/*.jar:/data0/zookeeper/bin/../conf:
2018-09-14 10:42:37,912 [myid:] - INFO [main:aaa@qq.com] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2018-09-14 10:42:37,912 [myid:] - INFO [main:aaa@qq.com] - Client environment:java.io.tmpdir=/tmp
2018-09-14 10:42:37,912 [myid:] - INFO [main:aaa@qq.com] - Client environment:java.compiler=<NA>
2018-09-14 10:42:37,913 [myid:] - INFO [main:aaa@qq.com] - Client environment:os.name=Linux
2018-09-14 10:42:37,913 [myid:] - INFO [main:aaa@qq.com] - Client environment:os.arch=amd64
2018-09-14 10:42:37,913 [myid:] - INFO [main:aaa@qq.com] - Client environment:os.version=3.10.0-693.el7.x86_64
2018-09-14 10:42:37,913 [myid:] - INFO [main:aaa@qq.com] - Client environment:user.name=root
2018-09-14 10:42:37,913 [myid:] - INFO [main:aaa@qq.com] - Client environment:user.home=/root
2018-09-14 10:42:37,914 [myid:] - INFO [main:aaa@qq.com] - Client environment:user.dir=/root
2018-09-14 10:42:37,916 [myid:] - INFO [main:aaa@qq.com] - Initiating client connection, connectString=192.168.17.64:2181 sessionTimeout=5000 aaa@qq.com
2018-09-14 10:42:37,962 [myid:] - INFO [main-SendThread(192.168.17.64:2181):aaa@qq.com] - Opening socket connection to server 192.168.17.64/192.168.17.64:2181. Will not attempt to authenticate using SASL (unknown error)
Welcome to ZooKeeper!
JLine support is enabled
2018-09-14 10:42:38,195 [myid:] - INFO [main-SendThread(192.168.17.64:2181):aaa@qq.com] - Socket connection established to 192.168.17.64/192.168.17.64:2181, initiating session
2018-09-14 10:42:38,234 [myid:] - INFO [main-SendThread(192.168.17.64:2181):aaa@qq.com] - Session establishment complete on server 192.168.17.64/192.168.17.64:2181, sessionid = 0x5425b250001, negotiated timeout = 5000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
[zk: 192.168.17.64:2181(CONNECTED) 0]
4、help 查看客户端帮助命令
在客户端交互命令行中,输入h
或者help命令查询可以使用的客户端命令:
[zk: 192.168.17.64:2181(CONNECTED) 0] h
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit
getAcl path
close
connect host:port
[zk: 192.168.17.64:2181(CONNECTED) 1]
这些命令的作用和关系型数据库的SQL语句类似,zk的命令是对节点和数据进行增删改查操作,而SQL则是对表的数据增册改查操作。下面详细介绍所有命令的使用方法:
5、查询子节点列表
语法:ls path
path:节点路径
[zk: 192.168.17.64:2181(CONNECTED) 1] ls /
[zookeeper]
目前根节点下只有zookeeper一个节点,是zk默认创建的,用于存储节点的一些状态信息,比如节点配额。
6、创建节点
语法:create [-s] [-e] path data acl
(可以注意一下各个版本的变化,如 create path [-s] [-e] data acl
)
-s:指定该节点是一个序列节点,创建同名的节点时,会给节点自动加上编号
-e:指定该节点是一个临时节点,默认是永久节点。临时节点会在客户端与服务器断开连接时,zk会将其创建的所有临时节点全部删除
path:节点路径
data:存储在节点中的数据
acl:设置子节点访问权限,默认所有人都可以对该节点进行读写操作
# 1> 在根目录创建了一个`node_01`的节点,指定的数据为mydata
[zk: 192.168.17.64:2181(CONNECTED) 2] create /node_01 mydata
Created /node_01
# 查看跟目录下节点
[zk: 192.168.17.64:2181(CONNECTED) 3] ls /
[node_01, zookeeper]
# 2> 创建一个临时节点(创建之后,可退出客户端重新登录查看该节点是否存在,来验证临时节点是否被删除)
[zk: 192.168.17.64:2181(CONNECTED) 4] create -e /node_02 "i is a ephemeral node"
Created /node_02
# 3> 创建一个序列临时节点
[zk: 192.168.17.64:2181(CONNECTED) 5] create -s -e /node_03 'i is a ephemeral sequence node'
Created /node_030000000015
# 4> 创建一个永久序列节点(节点会自动加上编号)
[zk: 192.168.17.64:2181(CONNECTED) 6] create -s /node_04 data
Created /node_040000000016
[zk: 192.168.17.64:2181(CONNECTED) 7] create -s /node_04 data
Created /node_040000000017
[zk: 192.168.17.64:2181(CONNECTED) 8] create -s /node_04 data
Created /node_040000000018
# 5> 创建一个带权限的节点,限制只能IP为192.168.1.101这台机器访问
## c:创建子节点权限
## d:删除子节点权限
## r:读取子节点列表的权限
## w:写权限,即修改子节点数据权限
## a:管理子节点权限
[zk: 192.168.17.64:2181(CONNECTED) 9] create /node_04 mydata ip:192.168.17.64:cdrwa
Created /node_04
[zk: 192.168.17.64:2181(CONNECTED) 10] ls /
[zookeeper, node_04, node_040000000016, node_040000000017, node_030000000015, node_02, node_01, node_040000000018]
注意:(1)创建节点必须要为节点设置数据,否则会创建不成功。
(2)断开重连之后,临时节点(node_02和node_03)自动消失。但是因为默认的心跳机制,有的时候查询临时节点还存在。当再次查询,临时节点就消失了。
# 退出后,重新登录
[zk: 192.168.17.64:2181(CONNECTED) 0] ls /
[zookeeper, node_04, node_040000000016, node_040000000017, node_01, node_040000000018]
7、获取节点数据和更新信息
语法:get path [watch]
path:节点路径
watch:监听节点数据变化。如果其它客户端修改了该节点的数据,则会通知监听了该节点的所有客户端。
[zk: 192.168.17.64:2181(CONNECTED) 1] get /zookeeper #下面空行说明节点内容为空
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
说明:
get: 内容为空
cZxid :创建节点的id
ctime : 节点的创建时间
mZxid :修改节点的id
mtime :修改节点的时间
pZxid :子节点的id
cversion : 子节点的版本
dataVersion : 当前节点数据的版本
aclVersion :权限的版本
ephemeralOwner :判断是否是临时节点,值不再是0,表示这个临时节点的版本号,如果是永久节点则值为0x0
dataLength : 数据的长度
numChildren :子节点的数量
节点下内容不为空的情况:
[zk: 192.168.17.64:2181(CONNECTED) 2] get /node_01
mydata
cZxid = 0x40000000f
ctime = Fri Sep 14 10:51:55 CST 2018
mZxid = 0x40000000f
mtime = Fri Sep 14 10:51:55 CST 2018
pZxid = 0x40000000f
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
/node_01
的节点数据为mydata
,即节点状态信息的第一行
watcher通知机制
关于watcher
机制大体的理解可以为,当每个节点发生变化,都会触发watcher
事件,类似于mysql
的触发器。zk
中 watcher
是一次性的,触发后立即销毁。可以参考https://blog.csdn.net/hohoo1990/article/details/78617336
- stat path [watch]
设置watch事件
- get path [watch]
设置watch事件
- 子节点创建和删除时触发watch事件,子节点修改不会触发该事件
8、获取节点状态
每个节点都包含描述该节点的一些状态信息,比如:节点数据、版本号等。
语法:stat path [watch]
path:节点全路径
watch:监听节点状态变化
[zk: 192.168.17.64:2181(CONNECTED) 3] stat /node_01
cZxid = 0x40000000f
ctime = Fri Sep 14 10:51:55 CST 2018
mZxid = 0x40000000f
mtime = Fri Sep 14 10:51:55 CST 2018
pZxid = 0x40000000f
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
在ZK中,ZK客户端对服务器每一个数据节点的写操作,ZK会认为都是一次完整的事务操作,要么成功,要么失败,保证了数据的原子性。而每次事务都会分配一个唯一的事务id,以标识这次事务操作的数据信息。下面详细理解一下节点状态各个字段的含义:
cZxid:创建节点的事务id
ctime:创建节点的时间
mZxid:修改节点的事务id
mtime:修改节点的时间
pZxid:子节点列表最后一次修改的事务id。删除或添加子节点,不包含修改子节点的数据。
cversion:子节点的版本号,删除或添加子节点,版本号会自增
dataVersion:节点数据版本号,数据写入操作,版本号会递增
aclVersion:节点ACL权限版本,权限写入操作,版本号会递增
ephemeralOwner:临时节点创建时的事务id,如果节点是永久节点,则它的值为0
dataLength:节点数据长度(单位:byte),中文占3个byte
numChildren:子节点数量
9、查询子节点列表及状态信息
语法:ls2 path [watch]
path:节点路径
watch:是否监听子节点列表变化通知
[zk: 192.168.17.64:2181(CONNECTED) 4] ls2 /zookeeper
[quota]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
第一行是/zookeeper
的子节点列表,后面的信息是/zookeeper
节点的状态信息。和ls
命令不一样的是,ls2
不仅能查询节点的子节点列表,同时也能查询到节点的状态信息,是ls命令和stat命令的整合。
10、设置节点数据
语法:set path data [version]
path:节点路径
data:节点数据
version:数据版本号(节点状态dataVersion的值)
[zk: 192.168.17.64:2181(CONNECTED) 5] get /node_01
mydata
cZxid = 0x40000000f
ctime = Fri Sep 14 10:51:55 CST 2018
mZxid = 0x40000000f
mtime = Fri Sep 14 10:51:55 CST 2018
pZxid = 0x40000000f
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
# 修改节点内容为hello
[zk: 192.168.17.64:2181(CONNECTED) 6] set /node_01 hello
cZxid = 0x40000000f
ctime = Fri Sep 14 10:51:55 CST 2018
mZxid = 0x400000018
mtime = Fri Sep 14 11:00:37 CST 2018
pZxid = 0x40000000f
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
# 查看修改后的信息
[zk: 192.168.17.64:2181(CONNECTED) 7] get /node_01
hello
cZxid = 0x40000000f
ctime = Fri Sep 14 10:51:55 CST 2018
mZxid = 0x400000018
mtime = Fri Sep 14 11:00:37 CST 2018
pZxid = 0x40000000f
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
此时可以看到dataVersion
状态的值变成了1。默认不加版本号则会覆盖节点之前设置的数据,如果加上版本号,版本号必须和服务器上的版本号一致,否则会报错,如下所示:
#set 根据版本号更新 dataVersion 乐观锁
[zk: 192.168.17.64:2181(CONNECTED) 8] set /node_01 test 1
cZxid = 0x40000000f
ctime = Fri Sep 14 10:51:55 CST 2018
mZxid = 0x400000019
mtime = Fri Sep 14 11:01:56 CST 2018
pZxid = 0x40000000f
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
# 因为数据的版本号已经修改为2 再次使用版本号1修改节点提交错误
[zk: 192.168.17.64:2181(CONNECTED) 9] set /node_01 testdata 1
version No is not valid : /node_01
这种机制和数据库中的乐观索机制非常相似。
想象一种场景,在获取某个节点的数据之后,利用数据处理完业务逻辑,不加版本号,直接修改节点的数据。但在获取和修改节点数据的这一小段时间窗内,很有可能有其它客户端也修改了该节点的数据,而节点数据变化会使节点状态的dataVersion值递增。如果我们获取节点数据处理完成自己的业务逻辑,然后不加上版本号直接修改节点数据时,则会覆盖掉其它客户端修改的最新数据,从而导致数据不一致的情况。所以要保证数据的一致性时,修改节点数据时,应该加上最新的版本号。而在这个场景中,我们在处理完业务逻辑,再修改节点数据时带上节点的版本号,这时若有其它节点修改了数据,修改则会失败。此时我们应该马上再获取一次节点的最新版本号,再做修改。
11、删除节点
语法:delete path [version]
path:节点路径
version:节点版本号(节点状态cversion的值),可选。如果传递了版本号,则必须保证和服务器的版本号一致,否则会报错:version No is not valid : 节点路径
[zk: 192.168.17.64:2181(CONNECTED) 10] delete /path/node_01/node_01_01
注意:delete只能删除没有子节点的节点,否则会报错,如下所示:
[zk: 192.168.17.64:2181(CONNECTED) 11] delete /node_04
Node not empty: /node_04
12、删除节点(包括子节点)
语法:rmr path
path:节点路径
[zk: 192.168.17.64:2181(CONNECTED) 12] rmr /node_04
rmr
会递归删除子节点,再删除节点本身
13、ACL权限控制
ZK的节点有5种操作权限:CREATE
、READ
、WRITE
、DELETE
、ADMIN
也就是 增、删、改、查、管理权限,这5种权限简写为crwda
(即:每个单词的首字符缩写)。
注:这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限
身份的认证有4种方式:
- world
:默认方式,相当于全世界都能访问
- auth
:代表已经认证通过的用户(cli中可以通过addauth digest user:pwd 来添加当前上下文中的授权用户)
- digest
:即用户名:密码这种方式认证,这也是业务系统中最常用的
- ip
:使用Ip地址认证
使用[scheme:id:permissions]
来表示acl权限
14、获取节点ACL
ACL是zk对节点权限控制的一种策略 ,getAcl获取某个节点的acl权限信息
语法:getAcl path
path:节点路径
[zk: 192.168.17.64:2181(CONNECTED) 21] getAcl /node_01
'world,'anyone
: cdrwa
创建节点时如果没有设置acl权限,默认为所有用户都可以对该节点进行读写操作。
15、设置节点ACL
语法:setAcl path acl
path:节点路径
acl:ACL权限模式
[zk: 192.168.17.64:2181(CONNECTED) 22] create /node_01/test test
Created /node_01/test
[zk: 192.168.17.64:2181(CONNECTED) 23] getAcl /node_01/test
'world,'anyone
: cdrwa
#设置节点权限 crwa 不允许删除
[zk: 192.168.17.64:2181(CONNECTED) 24] setAcl /node_01/test world:anyone:crwa
cZxid = 0x400000022
ctime = Fri Sep 14 11:10:13 CST 2018
mZxid = 0x400000022
mtime = Fri Sep 14 11:10:13 CST 2018
pZxid = 0x400000022
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#查询刚才设置的acl权限信息 crwa 没有删除权限
[zk: 192.168.17.64:2181(CONNECTED) 25] getAcl /node_01/test
'world,'anyone
: crwa
[zk: 192.168.17.64:2181(CONNECTED) 26] create /node_01/test/abc abc
Created /node_01/test/abc
#删除子节点的时候提交权限不足
[zk: 192.168.17.64:2181(CONNECTED) 27] delete /node_01/test/abc
Authentication is not valid : /node_01/test/abc
#设置节点的权限信息为rda
[zk: 192.168.17.64:2181(CONNECTED) 28] setAcl /node_01/test world:anyone:rda
cZxid = 0x400000022
ctime = Fri Sep 14 11:10:13 CST 2018
mZxid = 0x400000022
mtime = Fri Sep 14 11:10:13 CST 2018
pZxid = 0x400000024
cversion = 1
dataVersion = 0
aclVersion = 2
ephemeralOwner = 0x0
dataLength = 4
numChildren = 1
[zk: 192.168.17.64:2181(CONNECTED) 31] getAcl /node_01/test
'world,'anyone
: dra
#可以成功删除
[zk: 192.168.17.64:2181(CONNECTED) 32] delete /node_01/test/abc
[zk: 192.168.17.64:2181(CONNECTED) 33] ls /node_01/test
[]
#设置节点信息为a admin
[zk: 192.168.17.64:2181(CONNECTED) 34] setAcl /node_01/test world:anyone:a
cZxid = 0x400000022
ctime = Fri Sep 14 11:10:13 CST 2018
mZxid = 0x400000022
mtime = Fri Sep 14 11:10:13 CST 2018
pZxid = 0x400000027
cversion = 2
dataVersion = 0
aclVersion = 3
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#获取 设置都提示权限不足
[zk: 192.168.17.64:2181(CONNECTED) 35] get /node_01/test
Authentication is not valid : /node_01/test
[zk: 192.168.17.64:2181(CONNECTED) 36] set /node_01/test 123
Authentication is not valid : /node_01/test
设置/node_01
节点,只允许IP为192.168.1.101
的客户端访读写/node_01
的数据,但不允许创建、查询、删除子节点和不允许设置节点权限。节点ACL详细介绍请参考《分布式服务管理框架-Zookeeper节点ACL》
# 设置访问ip限制
[zk: localhost:2181(CONNECTED) 37] setAcl /node_01 ip:192.168.17.64:rcdwa
cZxid = 0x65
ctime = Sat Nov 12 17:29:06 CST 2016
mZxid = 0x65
mtime = Sat Nov 12 17:29:06 CST 2016
pZxid = 0x68
cversion = 3
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 3
numChildren = 3
acl Auth 密码明文设置
[zk: 192.168.17.64:2181(CONNECTED) 38] create /niocoder/merryyou merryyou
Created /niocoder/merryyou
#查询默认节点权限信息
[zk: 192.168.17.64:2181(CONNECTED) 39] getAcl /niocoder/merryyou
'world,'anyone
: cdrwa
#使用auth设置节点权限信息
[zk: 192.168.17.64:2181(CONNECTED) 40] setAcl /niocoder/merryyou auth:test:test:cdrwa
Acl is not valid : /niocoder/merryyou
# 注册test:test 账号密码
[zk: 192.168.17.64:2181(CONNECTED) 41] addauth digest test:test
[zk: 192.168.17.64:2181(CONNECTED) 42] setAcl /niocoder/merryyou auth:test:test:cdrwa
cZxid = 0x200000020
ctime = Sat Jun 02 16:32:08 UTC 2018
mZxid = 0x200000020
mtime = Sat Jun 02 16:32:08 UTC 2018
pZxid = 0x200000020
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
#查询节点权限信息 密码为密文格式
[zk: 192.168.17.64:2181(CONNECTED) 43] getAcl /niocoder/merryyou
'digest,'test:V28q/NynI4JI3Rk54h0r8O5kMug=
: cdrwa
acl digest 密码密文设置
[zk: 192.168.17.64:2181(CONNECTED) 44] create /names test
Created /names
[zk: 192.168.17.64:2181(CONNECTED) 45] getAcl /names
'world,'anyone
: cdrwa
#使用digest设置节点的权限信息 密码为test密文
[zk: localhost:2181(CONNECTED) 15] setAcl /names digest:test:V28q/NynI4JI3Rk54h0r8O5kMug=:cdra
cZxid = 0x400000006
ctime = Sun Jun 03 01:01:17 UTC 2018
mZxid = 0x400000006
mtime = Sun Jun 03 01:01:17 UTC 2018
pZxid = 0x400000006
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#查询节点权限信息
[zk: 192.168.17.64:2181(CONNECTED) 46] getAcl /names
'digest,'test:V28q/NynI4JI3Rk54h0r8O5kMug=
: cdra
#获取节点信息提示权限不足
[zk: 192.168.17.64:2181(CONNECTED) 47] get /names
Authentication is not valid : /names
# 注册账户
[zk: 192.168.17.64:2181(CONNECTED) 48] addauth digest test:test
# 可以正常获取
[zk: 192.168.17.64:2181(CONNECTED) 49] get /names
test
cZxid = 0x400000006
ctime = Sun Jun 03 01:01:17 UTC 2018
mZxid = 0x400000006
mtime = Sun Jun 03 01:01:17 UTC 2018
pZxid = 0x400000006
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#由于没有设置写权限不能修改节点 w
[zk: 192.168.17.64:2181(CONNECTED) 50] set /names 111
Authentication is not valid : /names
[zk: 192.168.17.64:2181(CONNECTED) 51] delete /names
acl ip 控制客户端
[zk: 192.168.17.64:2181(CONNECTED) 52] create /niocoder/ip aa
Created /niocoder/ip
[zk: 192.168.17.64:2181(CONNECTED) 53] get /niocoder/ip
aa
cZxid = 0x40000000a
ctime = Sun Jun 03 01:06:47 UTC 2018
mZxid = 0x40000000a
mtime = Sun Jun 03 01:06:47 UTC 2018
pZxid = 0x40000000a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0
# 添加ip控制的权限信息
[zk: 192.168.17.64:2181(CONNECTED) 54] setAcl /niocoder/ip ip:192.168.0.68:cdrwa
cZxid = 0x40000000a
ctime = Sun Jun 03 01:06:47 UTC 2018
mZxid = 0x40000000a
mtime = Sun Jun 03 01:06:47 UTC 2018
pZxid = 0x40000000a
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0
[zk: 192.168.17.64:2181(CONNECTED) 55] getAcl /niocoder/ip
'ip,'192.168.0.68
: cdrwa
acl super超级管理员
使用super
权限需要修改zkServer.sh
,添加super
管理员,重启zkServer.sh
"-Dzookeeper.DigestAuthenticationProvider.superDigest=test:V28q/NynI4JI3Rk54h0r8O5kMug="
nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.DigestAuthenticationprovider.superDigest=test:V28q/NynI4JI3Rk54h0r8O5kMug=" \
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
#重启进入zkCli
#由于之前设置ip权限,所以不允许访问
[zk: 192.168.17.64:2181(CONNECTED) 0] ls /niocoder/ip
Authentication is not valid : /niocoder/ip
#登录账号信息,即为管理员账号
[zk: 192.168.17.64:2181(CONNECTED) 1] addauth digest test:test
#正常访问,节点内容为空
[zk: 192.168.17.64:2181(CONNECTED) 2]ls /niocoder/ip
[]
[zk: 192.168.17.64:2181(CONNECTED) 3] get /niocoder/ip
aa
cZxid = 0x40000000a
ctime = Sun Jun 03 01:06:47 UTC 2018
mZxid = 0x40000000a
mtime = Sun Jun 03 01:06:47 UTC 2018
pZxid = 0x40000000a
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0
四字命令Four Letter Words
- 使用四字命令需要安装
nc
命令,(yum install nc
)
stat 查看状态信息
[aaa@qq.com bin]# echo stat | nc 192.168.17.64 2181
Zookeeper version: 3.4.11-37e277162d567b55a07d1755f0b31c32e93c01a0, built on 11/01/2017 18:06 GMT
Clients:
/192.168.0.68:49346[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/4
Received: 62
Sent: 61
Connections: 1
Outstanding: 0
Zxid: 0x50000000a
Mode: follower
Node count: 10
[aaa@qq.com bin]#
ruok 查看zookeeper是否启动
[aaa@qq.com bin]# echo ruok | nc 192.168.17.64 2181
imok[aaa@qq.com bin]#
dump 列出没有处理的节点,临时节点
imok[aaa@qq.com bin]# echo dump | nc 192.168.17.64 2181
SessionTracker dump:
aaa@qq.com7
ephemeral nodes dump:
Sessions with Ephemerals (0):
[aaa@qq.com bin]#
conf 查看服务器配置
[aaa@qq.com bin]# echo conf | nc 192.168.17.64 2181
clientPort=2181
dataDir=/usr/home/zookeeper-3.4.11/data/version-2
dataLogDir=/usr/home/zookeeper-3.4.11/data/version-2
tickTime=2000
maxClientCnxns=60
minSessionTimeout=4000
maxSessionTimeout=40000
serverId=2
initLimit=10
syncLimit=5
electionAlg=3
electionPort=3888
quorumPort=2888
peerType=0
[aaa@qq.com bin]#
cons 显示连接到服务端的信息
[aaa@qq.com bin]# echo cons | nc 192.168.17.64 2181
/192.168.0.68:49354[0](queued=0,recved=1,sent=0)
[aaa@qq.com bin]#
envi 显示环境变量信息
[aaa@qq.com bin]# echo envi | nc 192.168.17.64 2181
Environment:
zookeeper.version=3.4.11-37e277162d567b55a07d1755f0b31c32e93c01a0, built on 11/01/2017 18:06 GMT
host.name=localhost
java.version=1.8.0_111
java.vendor=Oracle Corporation
java.home=/usr/local/jdk1.8.0_111/jre
java.class.path=/usr/home/zookeeper-3.4.11/bin/../build/classes:/usr/home/zookeeper-3.4.11/bin/../build/lib/*.jar:/usr/home/zookeeper-3.4.11/bin/../lib/slf4j-log4j12-1.6.1.jar:/usr/home/zookeeper-3.4.11/bin/../lib/slf4j-api-1.6.1.jar:/usr/home/zookeeper-3.4.11/bin/../lib/netty-3.10.5.Final.jar:/usr/home/zookeeper-3.4.11/bin/../lib/log4j-1.2.16.jar:/usr/home/zookeeper-3.4.11/bin/../lib/jline-0.9.94.jar:/usr/home/zookeeper-3.4.11/bin/../lib/audience-annotations-0.5.0.jar:/usr/home/zookeeper-3.4.11/bin/../zookeeper-3.4.11.jar:/usr/home/zookeeper-3.4.11/bin/../src/java/lib/*.jar:/usr/home/zookeeper-3.4.11/bin/../conf:
java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.io.tmpdir=/tmp
java.compiler=<NA>
os.name=Linux
os.arch=amd64
os.version=3.10.0-514.10.2.el7.x86_64
user.name=root
user.home=/root
user.dir=/usr/home/zookeeper-3.4.11/bin
[aaa@qq.com bin]#
mntr 查看zk的健康信息
[aaa@qq.com bin]# echo mntr | nc 192.168.17.64 2181
zk_version 3.4.11-37e277162d567b55a07d1755f0b31c32e93c01a0, built on 11/01/2017 18:06 GMT
zk_avg_latency 0
zk_max_latency 4
zk_min_latency 0
zk_packets_received 68
zk_packets_sent 67
zk_num_alive_connections 1
zk_outstanding_requests 0
zk_server_state follower
zk_znode_count 10
zk_watch_count 0
zk_ephemerals_count 0
zk_approximate_data_size 124
zk_open_file_descriptor_count 32
zk_max_file_descriptor_count 4096
[aaa@qq.com bin]#
wchs 展示watch的信息
[aaa@qq.com bin]# echo wchs | nc 192.168.17.64 2181
0 connections watching 0 paths
Total watches:0
[aaa@qq.com bin]#
wchc和wchp 显示session的watch信息 path的watch信息
- 需要在 配置
zoo.cfg
文件中添加4lw.commands.whitelist=*
[aaa@qq.com bin]# echo wchc | nc 192.168.17.64 2181
wchc is not executed because it is not in the whitelist.
[aaa@qq.com bin]# echo wchp | nc 192.168.17.64 2181
wchp is not executed because it is not in the whitelist.
16、设置节点配额
节点可以存储数据,也可以创建子节点,但是如果不做控制,节点数据可以无限大,子节点数量也可以创建无数个,所以在有些场景下需要对节点的数据和子节点的数量需要做一些限制,zk为我们提供了setauota命令实现对子节点的限制功能。但是,zk并不是真正在的物理上对节点做了限制,而是如果超过了节点限制,会在zk的日志文件中记录配额超限的警告信息。
语法:setquota -n|-b val path
-n:限制子节点的数量
-b:限制节点的数据长度
val:根据-n和-b参数不同,val值的意义也不一样。如果是-n参数,val表示限制子节点的数量。如果是-b参数,val表示限制节点的数据长度
path:节点路径
[zk: 192.168.17.64:2181(CONNECTED) 4] setquota -n 2 /node_01
Comment: the parts are option -n val 2 path /node_01
上面我对/node_01
限制它最多只能有2个子节点,下面我在/node_01
节点下创建3个节点看看效果:
[zk: 192.168.17.64:2181(CONNECTED) 5] create /node_01/node_01_01 abc
Created /node_01/node_01_01
[zk: 192.168.17.64:2181(CONNECTED) 6] create /node_01/node_01_02 abc
Created /node_01/node_01_02
[zk: 192.168.17.64:2181(CONNECTED) 7] create /node_01/node_01_03 abc
Created /node_01/node_01_03
[zk: 192.168.17.64:2181(CONNECTED) 8] ls /node_01
[node_01_03, node_01_01, node_01_02]
你可能会觉得奇怪,我明明限制了/node_01
节点最多只能有2个节点,在创建第3个节点的时候并没有报错,也创建成功了,为什么限制没有起作用呢? 在上面我也提到了,zk并没有在物理上限制节点的数量和数据的长度,当节点超过了限制,zk只会在后台记录节点限制的日志信息。下面我们看下zk日志文件中输出的节点配额限制警告信息:
# 查看$ZK_HOME/conf/log4j.properties 中zookeeper.log.dir和zookeeper.log.file确定zookeeper.log位置
[aaa@qq.com ~]# tail /var/log/zookeeper/zookeeper.log
...
2018-09-14 11:29:20,196 [myid:] - WARN [SyncThread:0:aaa@qq.com] - Quota exceeded: /node_01 count=3 limit=2
日志中输出的警告信息count=3,表示/node_01
节点当前有3个子节点。limit=2,表示/node_01
节点最多只能有2个节点。
zk默认会在启动服务的目录生成一个zookeeper.out日志文件,即执行
zkServer.sh start
命令的目录。我修改了zk默认日志文件目录为/var/log/zookeeper
,你也可以参考《分布式服务管理框架-Zookeeper日志配置》自行修改。
17、查询节点配额
语法:listquota path
path:节点路径
[zk: 192.168.17.64:2181(CONNECTED) 0] listquota /node_01
absolute path is /zookeeper/quota/node_01/zookeeper_limits
Output quota for /node_01 count=2,bytes=-1
Output stat for /node_01 count=4,bytes=15
Output quota:表示节点的配额信息,限制该节点最多有2个子节点,节点数据为-1,表示不限制
Output stat:表示当前节点的状态信息,该节点有4个子节点,节点数据长度为12
18、删除节点配额
语法:delquota [-n|-b] path
-n:删除子节点数量配额限制
-b:删除节点数据长度配额限制
path:节点路径
# 删除/node_01节点子节点数量限制
[zk: 192.168.17.64:2181(CONNECTED) 1] delquota -n /node_01
[zk: 192.168.17.64:2181(CONNECTED) 2] listquota /node_01
absolute path is /zookeeper/quota/node_01/zookeeper_limits
# count=-1表示没有子节点数量限制
Output quota for /node_01 count=-1,bytes=-1
Output stat for /node_01 count=4,bytes=15
19、给当前客户端添加授权信息
语法:addauth scheme auth
scheme:授权方式
auth:权限 addauth
一般用于digest
授权方式添加授权信息。digest
是用户名和密码授权,语法:username:BASE64(SHA1(password))
[zk: 192.168.17.64:2181(CONNECTED) 3] addauth digest yangxin:123456
给当前客户端添加授权信息,授权模式为digest(用户名/密码授权),用户名为yangxin,密码为123456
20、查看历史命令
可查询之前执行过的命令,会列出前最后10条命令,和linux中的history命令功能一样
[zk: 192.168.17.64:2181(CONNECTED) 4] history
0 - listquota /node_01
1 - delquota -n /node_01
2 - listquota /node_01
3 - history
21、执行历史命令
语法:redo cmdno
cmdno:历史命令编号
[zk: 192.168.17.64:2181(CONNECTED) 5] redo 3
0 - listquota /node_01
1 - delquota -n /node_01
2 - listquota /node_01
3 - history
4 - history
和linux中!命令编号
命令的作用一样
22、与leader同步数据
语法:sync path
path:节点路径
在对某个znode进行读操作时,应该先执行sync方法,使得读操作的连接所连的zk实例能与leader进行同步,从而保证能读到最新的数据。
注意:sync调用是异步的,无需等待调用的返回,zk服务器会保证所有后续的操作会在sync操作完成之后才执行,哪怕这些操作是在执行sync之前被提交的。
[zk: 192.168.17.64:2181(CONNECTED) 6] sync /node_01
23、打开或关闭监听日志
在获取节点数据、子节点列表等操作时,都可以添加watch参数监听节点的变化,从而节点数据更改、子节点列表变更时收到通知,并输出到控制台。默认是打开,可以设置参数将其关闭。
语法:printwatches on|off
on:打开
off:关闭
[zk: 192.168.17.64:2181(CONNECTED) 7] printwatches off
24、关闭连接
close
命令会关闭当前客户端连接
25、连接到zk服务器
语法:connect host:port
host:port:IP和zk客户端端口
[zk: 192.168.17.64:2181(CONNECTED) 8] connect 192.168.17.65:2181
26、退出zkCli.sh
终端
[zk: 192.168.17.64:2181(CONNECTED) 9]quit