Zookeeper集群最好是奇数台,容灾性好一些,由于允许不过半节点挂掉,比如5台允许挂掉2台,4台允许挂掉1台
应用场景:
分布式应用:发布与订阅即所谓的配置管理,顾名思义就是将数据发布到zk节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。例如全局的配置信息,地址列表等就非常适合使用。
Name Service:这个主要是作为分布式命名服务,通过调用zk的create node api,能够很容易创建一个全局唯一的path,这个path就可以作为一个名称。序列化节点
分布式通知/协调:ZooKeeper中特有watcher注册与异步通知机制,能够很好的实现分布式环境下不同系统之间的通知与协调,实现对数据变更的实时处理。
使用方法 通常是不同系统都对ZK上同一个znode进行watch,监听znode的变化(包括znode本身内容及子节点的),其中一个系统update了 znode,那么另一个系统能够收到通知,并作出相应处理。
分布式锁:分布式锁,这个主要得益于ZooKeeper为我们保证了数据的强一致性,zk集群中任意节点(一个zk server)上的相同znode的数据是一定是相同的。
锁服务可以分为两类,一个是保持独占,另一个是控制时序。
集群管理:Hbase Master选举则是zookeeper经典的使用场景;
Storm集群管理
分布式队列:队列方面,一种是常规的先进先出队列,另一种是要等到队列成员聚齐之后的才统一按序执行。对于第二种先进先出队列,增加分布式锁服务以控制时序场景
使用:
Wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.5/zookeeper-3.4.5.tar.gz
tar -zxvf zookeeper-3.4.5.tar.gz
目录为/opt/soft/zookeeper-3.4.5
在/etc/profile 里配置:
JAVA_HOME
ZOOKEEPER_HOME
PATH
2. 配置
创建data目录:
$ZOOKEEPER/data,即/opt/soft/zookeeper-3.4.5/data
创建myid: /opt/soft/zookeeper-3.4.5/data/myid
Myid存server的id,可以是1,2,3…,必须唯一
创建: $ZOOKEEPER/conf/zoo.cfg
修改zoo.cfg,增加如下:
dataDir=/opt/soft/zookeeper-3.4.5/data
clientPort=2181
initLimit=10
syncLimit=5
tickTime=2000
server.1=master:2888:3888
server.2=slave1:2888:3888
host配置: /etc/hosts文件中添加
192.168.2.13 master ####ip +主机名
192.168.2.14 slave1 ####ip +主机名
其中server.X代表组成整个服务的机器,当服务启动时,会在数据目录下查找这个文件myid,这个文件中存有服务器的号码。下面会讲myid文件的配置。
initLimit和syncLimit是针对集群的参数
1.tickTime:CS通信心跳数
Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
tickTime以毫秒为单位。
tickTime:该参数用来定义心跳的间隔时间,zookeeper的客户端和服务端之间也有和web开发里类似的session的概念,而zookeeper里最小的session过期时间就是tickTime的两倍。
2.initLimit:LF初始通信时限
集群中的follower服务器(F)与leader服务器(L)之间 初始连接 时能容忍的最多心跳数(tickTime的数量)。
此配置表示,允许 follower (相对于 leader 而言的“客户端”)连接 并同步到 leader 的初始化连接时间,它以 tickTime 的倍数来表示。当超过设置倍数的 tickTime 时间,则连接失败。
如果在设定的时间段内,半数以上的跟随者未能完成同步,领导者便会宣布放弃领导地位,进行另一次的领导选举。如果zk集群环境数量确实很大,同步数据的时间会变长,因此这种情况下可以适当调大该参数。默认为10。
转载者(西门吹牛)PS:我在搭建kafka集群的时候,启动zookeeper集群的时候(kafka内置了zookeeper),好像这个参数没有默认值,而是需要配置的。
3.syncLimit:LF同步通信时限
集群中的follower服务器(F)与leader服务器(L)之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)。
此配置表示, leader 与 follower 之间发送消息,请求 和 应答 时间长度。如果 follower 在设置的时间内不能与leader 进行通信,那么此 follower 将被丢弃。所有关联到这个跟随者的客户端将连接到另外一个跟随着。
zkServer.sh start
zkServer.sh status 状态
没有出错信息,则成功启动
执行测试
在一台机器如server.1上进行一个写操作:
zkCli.sh -server master:2181
initLimit和syncLimit是针对集群的参数
1.tickTime:CS通信心跳数
Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
tickTime以毫秒为单位。
tickTime:该参数用来定义心跳的间隔时间,zookeeper的客户端和服务端之间也有和web开发里类似的session的概念,而zookeeper里最小的session过期时间就是tickTime的两倍。
2.initLimit:LF初始通信时限
集群中的follower服务器(F)与leader服务器(L)之间 初始连接 时能容忍的最多心跳数(tickTime的数量)。
此配置表示,允许 follower (相对于 leader 而言的“客户端”)连接 并同步到 leader 的初始化连接时间,它以 tickTime 的倍数来表示。当超过设置倍数的 tickTime 时间,则连接失败。
如果在设定的时间段内,半数以上的跟随者未能完成同步,领导者便会宣布放弃领导地位,进行另一次的领导选举。如果zk集群环境数量确实很大,同步数据的时间会变长,因此这种情况下可以适当调大该参数。默认为10。
转载者(西门吹牛)PS:我在搭建kafka集群的时候,启动zookeeper集群的时候(kafka内置了zookeeper),好像这个参数没有默认值,而是需要配置的。
3.syncLimit:LF同步通信时限
集群中的follower服务器(F)与leader服务器(L)之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)。
此配置表示, leader 与 follower 之间发送消息,请求 和 应答 时间长度。如果 follower 在设置的时间内不能与leader 进行通信,那么此 follower 将被丢弃。所有关联到这个跟随者的客户端将连接到另外一个跟随着。
initLimit和syncLimit是针对集群的参数
1.tickTime:CS通信心跳数
Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
tickTime以毫秒为单位。
tickTime:该参数用来定义心跳的间隔时间,zookeeper的客户端和服务端之间也有和web开发里类似的session的概念,而zookeeper里最小的session过期时间就是tickTime的两倍。
2.initLimit:LF初始通信时限
集群中的follower服务器(F)与leader服务器(L)之间 初始连接 时能容忍的最多心跳数(tickTime的数量)。
此配置表示,允许 follower (相对于 leader 而言的“客户端”)连接 并同步到 leader 的初始化连接时间,它以 tickTime 的倍数来表示。当超过设置倍数的 tickTime 时间,则连接失败。
如果在设定的时间段内,半数以上的跟随者未能完成同步,领导者便会宣布放弃领导地位,进行另一次的领导选举。如果zk集群环境数量确实很大,同步数据的时间会变长,因此这种情况下可以适当调大该参数。默认为10。
转载者(西门吹牛)PS:我在搭建kafka集群的时候,启动zookeeper集群的时候(kafka内置了zookeeper),好像这个参数没有默认值,而是需要配置的。
3.syncLimit:LF同步通信时限
集群中的follower服务器(F)与leader服务器(L)之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)。
此配置表示, leader 与 follower 之间发送消息,请求 和 应答 时间长度。如果 follower 在设置的时间内不能与leader 进行通信,那么此 follower 将被丢弃。所有关联到这个跟随者的客户端将连接到另外一个跟随着。
建立会话连接
zkCli.sh -timeout 0 -r -server ip:port
- 1
-timeout
:指定当前会话的超时时间。zookeeper依靠与客户端之间的心跳判断一个会话是否有效,timeout指服务器如果在timeout指定的时间内没有收到客户端的心跳包,就认为这个客户端失效。单位毫秒。 -r
:read-only。zookeeper的只读模式指zookeeper的服务器如果和集群中半数或半数以上的服务器失去连接以后,该服务器就不在处理客户端的请求了,但有时候任然希望这种故障发生时,机器可以向外提供读服务,这种情况下就可以使用只读模式。 -server
: 表示想要连接的服务器地址和端口。
zkClient常用命令
使用如下命令进入client交互界面
zkCli.sh -timeout 5000 -r -server master:2181
- 1
进入界面后开始使用zkClient,按h
zkClient的使用帮助:
[zk: slave2:2181(CONNECTED) 26] 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
可知,zkClient常用的操作和文件系统大致相同,主要包括查看、新增、修改、删除、配额、权限控制等,下面我们分别从这几个方面进行说明。
查
zkClient的查询值得是查询节点的数据和节点的状态。主要有使用stat列出节点的状态;使用get获得节点的数据;使用ls列出节点的子节点列表;使用ls2同时列出子节点的列表和节点的状态;
stat
获取节点的状态,使用方法:stat path
[zk: slave2:2181(CONNECTED) 3] stat /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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
在zookeeper中,每一次对数据节点的写操作(如创建一个节点)被认为是一次事务,对于每一个事务系统都会分配一个唯一的id来标识这个事务,cZxid就表示事务id,表示该节点是在哪个事务中创建的;
ctime:表示节点创建的时间;
mZxid:最后一次更新时的事务id;
mtime:最后一次更新时的时间;
pZxid: 表示该节点的子节点列表最后一次被修改的事务的id(为当前节点添加子节点,从当前节点的子节点中删除一个或多个子节点都会引起节点的子节点的列表的改变,而修改节点的数据内容则不在此列);
cversion = -1,dataVersion = 0,aclVersion = 0在第一篇博客中已经有过介绍,分别表示子节点列表的版本,数据内容的版本,acl版本;
ephemeralOwner:用于临时节点,表示创建该临时节点的事务id,如果当前节点是永久节点,这个值是固定的,为0;
datalength表示当前节点存放的数据的长度;
numChildren表示当前节点拥有的子节点的个数;
ls
获取节点的子节点列表,使用方法:ls path
[zk: slave2:2181(CONNECTED) 24] ls /
[node2, zookeeper, node1]
- 1
- 2
- 3
get
获取节点的数据,其结果是当前节点的值和stat该路径的值放在一起。使用方法:get path
[zk: slave2:2181(CONNECTED) 25] get /node1
4545
cZxid = 0x300000012
ctime = Sat Apr 08 09:15:54 CST 2017
mZxid = 0x300000015
mtime = Sat Apr 08 09:20:07 CST 2017
pZxid = 0x300000016
cversion = 1
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
ls2
获取节点的子节点列表以及stat该路径:ls2 path
[zk: slave2:2181(CONNECTED) 30] ls2 /node1
[dfd]
cZxid = 0x300000012
ctime = Sat Apr 08 09:15:54 CST 2017
mZxid = 0x300000015
mtime = Sat Apr 08 09:20:07 CST 2017
pZxid = 0x300000016
cversion = 1
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
增
zkClient的增加只有一个命令,那就是创建新的节点。使用方法: create [-s] [-e] path data acl
-s
表示创建顺序节点 -e
表示创建临时节点
acl表示创建的节点路径
data表示创建的节点的数据内容
创建一个普通的节点
[zk: slave2:2181(CONNECTED) 35] create /node1 1222
Created /node1
[zk: slave2:2181(CONNECTED) 36] ls2 /node1
[]
cZxid = 0x30000001a
ctime = Sat Apr 08 09:32:53 CST 2017
mZxid = 0x30000001a
mtime = Sat Apr 08 09:32:53 CST 2017
pZxid = 0x30000001a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
创建一个临时节点
[zk: slave2:2181(CONNECTED) 1] create -e /node 122
[zk: slave2:2181(CONNECTED) 3] ls2 /
[node, zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x300000020
cversion = 14
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
退出当前会话,再次运行ls命令查看,结果如下:
[zk: slave2:2181(CONNECTED) 0] ls2 /
[zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x300000021
cversion = 15
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: slave2:2181(CO
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
发现创建的临时节点node消失了,正如上一篇博客中所提到的那样,zookeeper的临时节点在客户端失联后会自动被删除。
创建一个顺序节点
[zk: slave2:2181(CONNECTED) 1] create -s /node1 123
Created /node10000000008
- 1
- 2
- 3
发现创建的顺序节点的名称和我们起的名字不太一样,后面加了字串,再次运行上述命令:
[zk: slave2:2181(CONNECTED) 2] create -s /node1 123
Created /node10000000009
[zk: slave2:2181(CONNECTED) 6] ls /
[node10000000008, zookeeper, node10000000009]
- 1
- 2
- 3
- 4
- 5
发现新增了一个节点,且节点的名称进行自增了。利用zk的顺序节点的性质,可以制作分布式的主键生成器。完成命名服务。
改
zkClien提供了一个修改命令:set path data [version]
修改一个普通节点的数据内容:
[zk: slave1:2181(CONNECTED) 6] get /node1
123
cZxid = 0x400000002
ctime = Sat Apr 08 17:20:33 CST 2017
mZxid = 0x400000002
mtime = Sat Apr 08 17:20:33 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
[zk: slave1:2181(CONNECTED) 7] set /node1 12344
cZxid = 0x400000002
ctime = Sat Apr 08 17:20:33 CST 2017
mZxid = 0x400000003
mtime = Sat Apr 08 17:21:07 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
修改数据内容的同时,注意dataversion变了,mZxid和mtime也变了增加了。不管每次修改的值是否和之前一样,其dataversion都会加1
修改的同时,加入dataversion校验:
[zk: slave1:2181(CONNECTED) 8] set /node1 12331 2
version No is not valid : /node1
[zk: slave1:2181(CONNECTED) 9] set /node1 12331 1
cZxid = 0x400000002
ctime = Sat Apr 08 17:20:33 CST 2017
mZxid = 0x400000005
mtime = Sat Apr 08 17:23:57 CST 2017
pZxid = 0x400000002
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
可知,增加了version校验之后,那么version就必须和修改之前的dataversion相同,否则抛出异常。
删
删除节点
delete path [version]
- 1
[zk: slave1:2181(CONNECTED) 17] stat /node1
cZxid = 0x400000002
ctime = Sat Apr 08 17:20:33 CST 2017
mZxid = 0x400000005
mtime = Sat Apr 08 17:23:57 CST 2017
pZxid = 0x400000008
cversion = 2
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
[zk: slave1:2181(CONNECTED) 18] delete /node1 1
version No is not valid : /node1
[zk: slave1:2181(CONNECTED) 19] delete /node1 2
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
version和修改时的version意义是一样的,也是用于校验。
注意这个命令中的node必须是没有子节点的,否则抛出异常:
[zk: slave1:2181(CONNECTED) 23] ls /node1
[node11]
[zk: slave1:2181(CONNECTED) 24] delete /node1
Node not empty: /node1
- 1
- 2
- 3
- 4
- 5
那么如何删除含有子节点的节点呢? zookeeper提供了另外一个命令:rmr path
[zk: slave1:2181(CONNECTED) 26] ls /node1
[node11]
[zk: slave1:2181(CONNECTED) 27] rmr /node1
[zk: slave1:2181(CONNECTED) 28] ls /node1
Node does not exist: /node1
- 1
- 2
- 3
- 4
- 5
- 6
配额
设置配额
zookeeper提供类似文件系统的配额功能,不同的是zk的配额用于限制节点的数据内容和子节点的个数:setquota -n|-b val path
-n表示限制子节点的个数 val表示个数 path表示想要进行设置的那个node;下面的例子是对/test这个节点的子节点个数进行限制,最多为3个子节点
- 1
- 2
[zk: slave1:2181(CONNECTED) 36] setquota -n 3 /test
Comment: the parts are option -n val 3 path /test
- 1
- 2
- 3
那么进行了配额限制之后,再添加子节点试试
[zk: slave1:2181(CONNECTED) 41] create /test/node1 123452
Created /test/node1
[zk: slave1:2181(CONNECTED) 42] create /test/node2 123452
Created /test/node2
[zk: slave1:2181(CONNECTED) 43] create /test/node3 123452
Created /test/node3
[zk: slave1:2181(CONNECTED) 44] create /test/node4 123452
Created /test/node4
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
为什么还可以继续添加呢?大家可能感到奇怪,明明设置的配额中子节点的数目为3,但是我们在/node1创建了多于3的节点,为什么不抱错?实际上配额超限了之后,zookeeper只会在日志中进行警告记录,而不会抛出异常 。日志记录如下:
2017-04-08 17:44:39,427 [myid:1] - WARN [CommitProcessor:1:DataTree@
301] - Quota exceeded: /test count=9 limit=3
- 1
- 2
上述日志表示:超出了配额的限制,我们对节点限制了只能有3个子节点,但是现在有8个子节点
-b表示限制数据值的长度 val表示长度 path表示想要进行设置的那个node; 下面的例子是对node进行数据长度的配额限制
- 1
- 2
[zk: slave1:2181(CONNECTED) 15] setquota -b 4 /node2
Comment: the parts are option -b val 4 path /node2
- 1
- 2
- 3
修改节点的数据长度,使之超出配额,看看会发什么情况:
[zk: slave1:2181(CONNECTED) 16] set /node2 1234567
cZxid = 0x400000028
ctime = Sat Apr 08 17:52:38 CST 2017
mZxid = 0x40000002c
mtime = Sat Apr 08 17:53:20 CST 2017
pZxid = 0x400000028
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
同-n限额一样,并没有报错,只是在日志中做了相应的记录:
2017-04-08 17:53:20,889 [myid:1] - WARN [CommitProcessor:1:DataTree@
347] - Quota exceeded: /node2 bytes=7 limit=4
- 1
- 2
上述日志表示:超出了配额的限制,我们对节点限制了数据长度为4,但是现在数据长度为7。
查看配额
[zk: slave1:2181(CONNECTED) 25] listquota /node2
absolute path is /zookeeper/quota/node2/zookeeper_limits
Output quota for /node2 count=-1,bytes=-1
Output stat for /node2 count=1,bytes=7
- 1
- 2
- 3
- 4
- 5
第一行表示,对子节点数目没有限制,对数据的长度没有限制
第二行表示,子节点数目和/node2一共有1个,数据长度为7,数据长度为自己的长度加上所有的子节点的数据长度
删除配额
[zk: slave1:2181(CONNECTED) 30] delquota -n /node2
[zk: slave1:2181(CONNECTED) 31] delquota -b /node2
- 1
- 2
- 3
历史记录的查看和重新执行
[zk: slave1:2181(CONNECTED) 33] history
23 - delquota -b /node2
24 - setquota -n 3 /node2
25 - listquota /node2
26 - ls /node2
27 - get /node2
28 - create /node2/dfd 3434
29 - listquota /node2
30 - delquota -n /node2
31 - delquota -b /node2
32 - h
33 - history
[zk: slave1:2181(CONNECTED) 34] redo 26
[dfd]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
打开新的连接和关闭
connect slave1:2181
close
- 1
- 2
最后
另外还有一个重要的客户端命令,那就是对节点的ACL进行设置,由于ACL的重要性,我们将在下一篇进行说明和联系。
最后
退出zkCli命令:quit
ACL全称为Access Control List(访问控制列表),用于控制资源的访问权限。zk利用ACL策略控制节点的访问权限,如节点数据读写、节点创建、节点删除、读取子节点列表、设置节点权限等。
在传统的文件系统中,ACL分为两个维度,一个是属组,一个是权限,一个属组包含多个权限,一个文件或目录拥有某个组的权限即拥有了组里的所有权限,文件或子目录默认会继承自父目录的ACL。而在Zookeeper中,znode的ACL是没有继承关系的,每个znode的权限都是独立控制的,只有客户端满足znode设置的权限要求时,才能完成相应的操作。Zookeeper的ACL,分为三个维度:scheme、id、permission,通常表示为:scheme:id:permission,schema代表授权策略,id代表用户,permission代表权限。下面从这三个维度分别来介绍。
一、scheme
scheme即采取的授权策略,每种授权策略对应不同的权限校验方式。下面是zk常用的几种scheme:
1> digest
语法:digest:username:BASE64(SHA1(password)):cdrwa
digest:是授权方式
username:BASE64(SHA1(password)):是id部分
cdrwa:权限部份
用户名+密码授权访问方式,也是常用的一种授权策略。id部份是用户名和密码做sha1加密再做BASE64加密后的组合,比如设置一个节点的用户名为yangxin,密码为123456,则表示方式为:yangxin:BASE64(SHA1(123456))
⇒ yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=
。密码加密需要用到zk的一个工具类来生成,如下所示:
shell> java -Djava.ext.dirs=/usr/local/zookeeper/lib -cp /usr/local/zookeeper/zookeeper-3.4.9.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider yangxin:123456
yangxin:123456->yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=
- 1
- 2
- 3
本文的Zookeeper安装在:
/usr/local/zookeeper
下面是演示创建节点,并添加授权信息操作节点的示例:
## 创建节点/node_05
shell> create /node_05 data
Created /node_05
## 设置权限
shell> setAcl /node_05 digest:yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=:cdrwa
cZxid = 0x8e
ctime = Mon Nov 14 21:38:52 CST 2016
mZxid = 0x8e
mtime = Mon Nov 14 21:38:52 CST 2016
pZxid = 0x8e
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
## 获取节点刚刚设置的权限
shell> getAcl /node_05
'digest,'yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=
: cdrwa
## 没有授权,创建节点失败
shell> create /node_05/node_05_01 data
Authentication is not valid : /node_05/node_05_01
## 添加授权信息
shell> addauth digest yangxin:123456
## 添加授权信息后,就可以正常操作了
shell> create /node_05/node_05_01 data
Created /node_05/node_05_01
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
2> ip
基于客户端IP地址校验,限制只允许指定的客户端能操作znode。
比如,设置某个节点只允许IP为192.168.1.100
的客户端能读写该写节点的数据:ip:192.168.1.100:rw
shell> setAcl /node_08 ip:192.168.1.100:rw
- 1
3> world
语法:world:anyone:cdrwa
创建节点默认的scheme,所有人都可以访问。如下所示:
shell> create /node_06 data
Created /node_06
shell> getAcl /node_06
'world,'anyone
: cdrwa
- 1
- 2
- 3
- 4
- 5
上面主要介绍了平时常用的三种scheme,除此之外,还有host、super、auth授权策略。
二、id
id是验证模式,不同的scheme,id的值也不一样。scheme为digest时,id的值为:username:BASE64(SHA1(password))
,scheme为ip时,id的值为客户端的ip地址。scheme为world时,id的值为anyone
。
三、permission
在介绍scheme的时候,提到了acl的权限,如:digest:username:BASE64(SHA1(password)):cdrwa
中的cdrwa即是permission。
1> CREATE(r):创建子节点的权限
2> DELETE(d):删除节点的权限
3> READ(r):读取节点数据的权限
4> WRITE(w):修改节点数据的权限
5> ADMIN(a):设置子节点权限的权限
## 创建/node_8节点,acl为cd(只能创建和删除子节点)
shell> create /node_08 data digest:yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=:cd
Created /node_08
## 没有WRITE的权限,修改/node_8节点的数据失败
shell> set /node_8 update_data
Authentication is not valid : /node_08
## 没有READ的权限,读取子节点数据及查询子节点列表失败
shell> get /node_8
Authentication is not valid : /node_08
shell> ls /node_8
Authentication is not valid : /node_08
## 没有ADMIN权限,设置节点权限失败
shell> setAcl /node_08 ip:192.168.1.100:cdrwa
Authentication is not valid : /node_08
## 具备WRITE权限,可以创建节点
shell> create /node_08/node_08_01 abc
Created /node_08/node_08_01
## 具备DELETE权限,可以删除子节点
shell> delete /node_08/node_08_01
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
注意:cd权限用于控制子节点,rwa权限用于控制节点本身
启动过程中出现问题可以查看zookeeper.out日志:
displays the first 6 lines of a file
head -6 readme.txt
(2) displays the last 25 lines of a file
tail -25 mail.txt
范例一是显示档案的前 6 行,范例二则是显示档案最后的 25 行。
ps -ef|grep zkServer查看zk进程是否存在
import java.io.IOException; import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooKeeper; public class Zookeeper_Constructor_Usage_Simple implements Watcher { private static CountDownLatch connectedSemaphore = new CountDownLatch(1); @Override public void process(WatchedEvent event) { System.out.println("Receive watched event : " + event); if (KeeperState.SyncConnected == event.getState()) { connectedSemaphore.countDown(); } } public static void main(String[] args) throws IOException { ZooKeeper zookeeper = new ZooKeeper("127.0.0.1:2181", 5000, new Zookeeper_Constructor_Usage_Simple()); System.out.println(zookeeper.getState()); try { connectedSemaphore.await();
String path1 = zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); System.out.println("Success create znode: " + path1); String path2 = zookeeper.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); System.out.println("Success create znode: " + path2);} catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Zookeeper session established" ); }}