在zk的bin目录下:
1、官方提供的通过 ./zkCli.sh 打开zk 的客户端进行命令行后台
在客户端命令行打开help:
2、ls 和 ls2 命令
3、get 和 stat 命令
比较ls、ls2、stat命令:
可以看出,ls2 相当于 ls + stat。
get命令:获取指定的节点的数据
可以看出上面根路节点数据为空。
4、zk特性① - session的基本原理
(1)客户端与服务端之间的连接存在会话 - session
(2)每个会话都可以设置一个超时时间
(3)心跳结束,session则过期
客户端会定期给服务端发送消息表示自己还活着(还有心跳),如果,客户端没发消息,则服务端就会把客户端删掉。
(4)session过期,则所有通过这个session创建的临时节点znode都会被抛弃。
(5)心跳机制:客户端向服务端的ping包请求。
5、基于znode的命令
(1) create命令: create [-s] [-e] path data ac 【增】
eg:
默认创建节点
create /imooc imooc-data:创建了节点 /imooc,并存储值 imooc-data;
get /imooc:获取节点/imooc的信息;
此时,创建节点时没有设置其他参数,采用的是默认的,即非顺序且持久化的。
创建临时节点
create -e /imooc/tmpw tmp-data # -e表示临时节点
get /imooc
上面cversion表示子节点个数。
判断一个节点是临时还是持久
stat 指定节点 如:stat /imooc/tmpw
ephemeralOwner字段不是 0x0,表示是临时节点~
删除临时节点
在当前回话窗口,ctrl + c,则session断开连接,则此session创建的临时节点tempw将被删除。
在断开连接后,马上再次连接客户端查看/imooc下面的临时节点还在不在:
为啥还在呢???因为,zk是有心跳机制的,客户端断开连接没有向服务端发消息了,但是还是要在一定的时间比如20s之后才会将这个session所创建的临时节点删除。那过了一会儿了,在此查看/imooc下就没有临时节点tmpw了。
新建顺序节点
create -s /imooc/sec seq
即会被按顺序由小到大累加递增重命名。
(2)set命令:set path data [version] 【改】
在不设置当前版本号时,节点的数据版本号会自动默认+1。
在设置当前版本号时,假设有很多客户端同时访问一个节点,其中某个客户端在修改节点数据时,获取的当当前版本号不是最新的,就会报错。这就是乐观锁。
(3)delete命令:delete path [version]【删】
eg:删除节点/imooc/sec0000000002
同样,在删除或者更新节点时,如果获取的版本号不匹配最新的版本号,就会报错,这就是乐观锁。
so,在执行更新或者删除操作时,尽量以一个版本号来做,这样可以做到一个乐观锁的一个效果。
6、zk特性② - watcher机制
(1)针对每个节点的操作,都会有一个监督者 -> watcher。
(2)当监控的某个对象(znode)发生了变化,则触发watcher事件:只有当用户通过客户端操作了节点才会触发watcher事件。
(3)zk中的watcher是一次性的,触发后立即销毁。
(4)父节点、子节点增删改都能触发其watcher
(5)针对不同类型的操作,触发的watcher事件也不同:
①(子)节点创建事件;
②(子)节点删除事件;
③(子)节点数据变化事件;
根据用户的不同类型的操作,触发不同的watcher事件,反馈给用户不同的提醒。
7、Watcher命令行
(1)通过 get path [watch] 设置watcher
(2)父节点 增删改 操作触发watcher
(3)子节点 增删改 操作触发watcher
8、Watcher事件类型
Part1:针对父节点的操作触发watcher
(1)修改父节点数据触发:NodeDataChanged【改】
eg:
先获取节点的状态信息,用 stat或者get设置watch:
再给该节点更新:
可以看出触发了watcher事件:NodeDataChanged事件。
(2)创建父节点触发:NodeCreated【增】
eg:
先用 stat 获取一个父节点的信息,并设置watch,再创建该节点:
可以看出触发了NodeCreated事件。
(3)删除父节点触发:NodeDeleted【删】
eg:
先用get对节点设置watch:
再删除该节点:
可以看到触发了NodeDelete事件。
Note:zk的触发事件是一次性的,即在一次触发之后对该节点设置的watch就失效了。
Part2:针对子节点的操作触发watcher
(1)ls为父节点设置watcher,创建子节点触发:NodeChildrenChanged
(2)ls为父节点设置watcher,删除子节点触发:NodeChildrenChanged
(3)ls为父节点设置watcher,修改子节点不触发事件
so,怎么让修改子节点时触发watcher事件呢?就是把子节点当做父节点来做就好啦~
9、Watcher常用使用场景
其实就是把watcher作为一个触发器来用。
(1)统一资源配置
例如此时有个有三台机子的集群,每台机子的节点配置都一致(都设置了watcher)。在主机上更新节点为新的配置信息,那该节点的watcher检测到数据的更改,触发watcher事件,与此节点连接的客户端们检测到节点的watcher事件(具体的由watcher返回事件的具体类型比如新增节点或更改节点数据等),客户端由具体的事件类型,进行相应的配置更改。同时,由于zk的统一配置机制,集群中的其他机子也相应的进行一致的更改。
10、ACL(Access control lists)权限控制
(1)针对节点可以设置相关的读写等权限,目的是为了保障数据安全性
(2)权限permission可以指定不同的权限范围以及角色
11、ACL命令行
(1)getAcl:获取某个节点的acl权限信息
上图是zk赋的默认权限。
(2)setAcl:设置某个节点的acl权限信息
(3)addauth:输入认证授权信息,注册时输入明文密码(登录),但是在zk的系统里,密码是以加密的形式存在的
12、ACL的构成(一)
(1)zk的acl通过 [ scheme:id:permissions ]来构成权限列表
scheme:代表采用的某种权限机制
id:代表允许访问的用户
permission:权限组合字符串
13、ACL的构成(二) - scheme
(1)world:world下只有一个id,即只有一个用户,也就是anyone,那么组合的写法就是
world:anyone:[permissions]
(2)auth:代表认证登录,需要注册用户有权限就可以,形式为
auth:user:password:[permissions]
(3)digest:需要对密码加密才能访问,组合形式为
digest:username:BASE64(SHA1(password)):[permissions]
(4)简而言之,auth与digest的区别就是,前者明文, 后者密文;
setAcl / path auth:lee:lee:cdrwa 与 setAcl / path digest:lee:BASE64(SHA1(password))cdrwa 是等价的,在通过 addauth digest lee:lee 后都能操作指定节点的权限
(5)ip:当设置ip为指定的IP地址,此时限制ip进行访问,比如
ip:192.168.1.1:[permissions]
(6)super:代表超级管理员,拥有所有的权限;
14、ACL的构成(三) - permissions
字符串缩写 crdwa
(1)CREATE:创建子节点
(2)READ:获取节点/子节点
(3)WRITE:设置节点数据
(4)DELETE:删除子节点
(5)ADMIN:设置权限
15、ACL命令行学习(一)
(1)world:anyone:cdrwa
eg:
zk的默认权限 cdrwa。
给该节点设置权限:
删除该节点:
给该父节点再设置权限,进行删除:
(2)auth 和 digest
auth:user:pwd:cdrwa
digest:user:BASE64(SHA1(pwd)):cdrwa
addauth digest user:pwd
先查看/names节点的权限,是默认的cdrwa;
setAcl /names auth:用户名:密码 cdrwa 。是对关于/names节点已经注册入库的用户进行专有的权限设置。报错因为/names节点的用户未注册。
so,先进行所有范围内的用户名密码的注册入库(不仅限于该节点的用户,/names节点的用户需要在setAcl /names auth::cdrwa进行该节点用户的注册,此后库中的所有用户就获得该节点的访问权限):
所有范围内的用户名密码注册入库登录方法一:使用auth
此时密码写的时候,写的是明文,但是后面用getAcl查看,库里的密码是以密文的形式保存的。
addauth digest xiaohong:123
此时用户已经注册登录上了,但没具体的指定认证哪个节点。
再对库中的用户进行该节点的 认证 及 权限设置:
因为该节点进行用户认证的时候,重新授权所填写的用户名密码不起作用,是以库中的用户名密码为准登录。库里的用户名密码都可以登录,所以在认证的时候用户名密码可以省去不写。
上图因为上上一步我在库中注册了两组用户名密码,即这两个用户都可以登录此节点。
所有范围内的用户名密码注册入库登录方法二:使用digest
setAcl /names digest:用户名:密文:cdrwa
这里的加密用的是BASE64和SHA1双重加密。法二就是在库中注册登录和认证用户两个步骤一步到位。
在退出当前用户时,即ctrl+c,再次登录查看/names节点:
因为之前我们给/names节点对库里的用户进行了认证,所以只有库里的用户有权限查看该节点信息。如果库里没有用户即所有人可以直接查看节点信息,如果库里有用户,但是该节点没有对库里的用户进行认证,那么也是所有人可以直接查看节点信息。
先登录查看/names节点:
因为/names节点之前进行了库中用户的认证,即库中所有用户具有节点的访问权限,所以用可以用库中的某个用户名密码进行登录,就可以访问已经进行用户认证的节点。
不管之前用的是auth还是digest进行的库注册, 在这里 都是使用明文登录:
addauth digest 用户名:密码
总结:
(1)用户验证登陆:
法一:用addauth 先在库中注册用户名密码进行登录,之后再用 setAcl 节点 auth::dcrwa 进行用户认证;
法二:用digest 在登录的时候,直接注册用户名密码登录认证 一步到位;
(2)auth 与 digest区别:
auth注册的时候是写明文,digest是写密文。 库里的密码都是以密文的形式保存。
(3)digest的安全性相较而言比较高。