prev:ZooKeeper 1:简介与安装
节点类型
前一篇笔记里面介绍了,ZooKeeper的数据模型类似于文件系统的结构,是一个树状的。也就是说,里面也会有节点的概念。
前面的文章里面,尝试使用命令行创建了节点,例如:
我们按照上图的结构建立这个节点树,语句如下:
// 创建节点locks
[zk: 127.0.0.1:2181(CONNECTED) 18] create /locks
// 创建临时节点DBLock和myLock
[zk: 127.0.0.1:2181(CONNECTED) 19] create -e /locks/DBLock
Created /locks/DBLock
[zk: 127.0.0.1:2181(CONNECTED) 20] create -e /locks/myLock
Created /locks/myLock
// 创建节点jobs
[zk: 127.0.0.1:2181(CONNECTED) 27] create /jobs
// 创建3个临时有序节点
[zk: 127.0.0.1:2181(CONNECTED) 28] create -e -s /jobs/job
Created /jobs/job0000000003
[zk: 127.0.0.1:2181(CONNECTED) 30] create -e -s /jobs/job
Created /jobs/job0000000004
[zk: 127.0.0.1:2181(CONNECTED) 31] create -e -s /jobs/job
Created /jobs/job0000000005
// 创建容器节点work
[zk: 127.0.0.1:2181(CONNECTED) 34] create -c /work
Created /work
// 为张三创建容器节点zs-work
[zk: 127.0.0.1:2181(CONNECTED) 35] create -c /work/zs-work
Created /work/zs-work
// 为李四创建容器节点ls-work
[zk: 127.0.0.1:2181(CONNECTED) 36] create -c /work/ls-work
Created /work/ls-work
// 为老王创建容器节点lw-work
[zk: 127.0.0.1:2181(CONNECTED) 37] create -c /work/lw-work
Created /work/lw-work
这样我们就创建起来了
可以看到,根据上图的区别,存在几种不同的节点类型,他们具有不同的生命周期
类型 | 生命周期 | 创建示例 |
---|---|---|
普通节点(持久节点 persistent_node) | 一直存在,一直存储在ZooKeeper 服务器上,即使创建该节点的客户端与服务端的会话关闭了,该节点依然不会被删除 | create /locks |
临时节点 ephemeral | 当创建该临时节点的客户端会话因超时或发生异常而关闭时,该节点也相应在 ZooKeeper 服务器上被删除。 | create -e /locks/DBLock |
有序节点 sequential node | 并不算是一种单独种类的节点,而是在之前提到的持久节点和临时节点特性的基础上,增加了一个节点有序的性质。在我们创建有序节点的时候会自动使用一个单调递增的数字作为后缀 | create -e -s /jobs/job (有序临时节点) |
容器节点 container node | 当一个容器节点的最后一个孩子被删除后,容器节点也会被删除 | create -c /work |
TTL节点 ttl node | 当一个TTL节点在 TTL 内没有被修改并且没有子节点,会被删除。注意:默认此功能不开启,需要修改配置文件extendedTypesEnabled=true | create -t 3000 /ttl_node |
注意:容器节点和TTL节点需要版本在3.6.0以上,且TTL节点需要在配置文件中开启。
这里的ZooKeeper节点有个具体的名字:ZNode
节点属性
类似于树状结构,节点下面是可以存储一些信息和属性的。可以通过stat命令来进行查看。
[zk: 127.0.0.1:2181(CONNECTED) 39] stat /locks
cZxid = 0x8
ctime = Fri Jun 10 14:26:56 CST 2022
mZxid = 0x8
mtime = Fri Jun 10 14:26:56 CST 2022
pZxid = 0xc
cversion = 2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2
可以看出节点是存储了很多信息的。节点是由一些基本的属性构成:
基本属性 | 含义 |
---|---|
Zxid | ZooKeeper事务ID,每个更改都会有一个唯一的 zxid,类似于数据库中的事务号 |
Version numbers | 对节点的每次更改都会导致该节点的版本号增加。三个版本号分别是version(znode的数据变化次数)、cversion(znode子节点的变化次数)和aversion(znode的ACL变化次数) |
Ticks | 在使用多服务器 ZooKeeper 时,服务器使用 ticks 来定义事件的计时,例如状态上传、会话超时、对等方之间的连接超时等 |
Real time | znode创建修改时的时间戳 |
那么stat里面的属性的含义是什么呢
属性 | 含义 |
---|---|
czxid | 导致创建此znode的zxid |
mzxid | 最后修改此znode的zxid |
pzxid | 最后修改此znode子节点的 zxid |
ctime | 创建时间 |
mtime | 上次修改时间 |
version | 数据更改次数 |
cversion | 子节点的更改数 |
aversion | ACL的更改次数 |
ephemeralOwner | 如果是临时节点,该字段是所有者的会话id;如果不是临时节点,字段为零 |
dataLength | 此znode的数据字段的长度 |
numChildren | 此znode的子节点数 |
访问控制
ZooKeeper使用ACL来控制对znode的访问。和Linux的访问权限控制非常相似,ZooKeeper的ACL也是使用权限位来允许/禁止针对节点的各种操作以及这些权限适用的范围。
一个 ACL 权限设置通常可以分为 3 部分,分别是:
- 权限模式(Scheme)
- 授权对象(ID)
- 权限信息(Permission)
最终组成一条例如scheme : id : permission格式的ACL请求信息。
授权模式
ZooKeeper的权限验证方式大体分为两种类型
- 范围验证
范围验证类似于一些防火墙的配置。ZooKeeper可以针对一个IP或者一个IP段授予权限。例如 ip:192.168.0.11/22 - 口令验证
用户名密码的方式。
官网上,内置的授权模式有以下几种:
- world 任何人无需权限检查
- auth 忽略任何提供的权限表达式,使用已经通过认证的用户
- digest 使用username:password字符串生成 MD5 哈希,然后将其用作ACL ID身份
- IP 使用客户端IP进行访问控制
- x509 使用客户的X500名表示用户。详见文档
授权对象
授权对象是要把权限赋予谁。IP方式下是一个IP地址,digest是一个用户名,等等。
权限信息
支持以下的权限:
- CREATE 允许创建子节点
- READ 允许从节点获取数据并列出子节点
- WRITE 允许写数据
- DELETE 允许删除数据
- ADMIN 允许设置权限
其中,Create和Delete是不同于Write的,如果只允许Create不允许Delete意味着只能创建子节点不能删除子节点。
注意:权限信息不是递归授予的!子节点权限不会继承自父节点
可以理解为在一个部门中,需要对用户的权限进行控制。例如一个开发部门,里面有主管、开发人员、实习生,其中主管可以进行数据读、写、新增、删除,但是开发人员只能对自己的模块进行读和写,不能随意创建任务,实习生只能进行读,不能对线上的内容进行修改。
可插拔身份验证接口
ZooKeeper提供了一种权限扩展机制来让用户实现自己的权限控制方式。
要想实现自定义的权限控制机制,需要继承接口AuthenticationProvider,用户通过该接口实现自定义的权限控制。
public interface AuthenticationProvider {
// 返回标识插件的字符串
String getScheme();
// 将用户和验证信息关联起来
KeeperException.Code handleAuthentication(ServerCnxn cnxn, byte authData[]);
// 验证id格式
boolean isValid(String id);
// 将认证信息与ACL进行匹配看是否命中
boolean matches(String id, String aclExpr);
// 是否授权
boolean isAuthenticated();
}
在3.6之后,也可以选择继承类ServerAuthenticationProvider
public abstract class ServerAuthenticationProvider implements AuthenticationProvider {
/**
* 参数:
* ZooKeeperServer: ZooKeeperServer 实例
* ServerCnxn: 当前连接
* path : 正在操作的ZNode路径(如果不使用,则为 null)
* perm : 操作值 或 0
* setAcls : 操作setAcl()方法时,正在设置的ACL列表
*/
public abstract KeeperException.Code handleAuthentication(ServerObjs serverObjs, byte authData[]);
public abstract boolean matches(ServerObjs serverObjs, MatchValues matchValues);
}
参考
ZooKeeper Programmer’s Guide
ZooKeeper-cli: the ZooKeeper command line interface
03 ACL 权限控制:如何避免未经授权的访问?