ZooKeeper学习第六期---ZooKeeper机制架构

1、ZooKeeper权限管理机制 

1.1 权限管理ACL(Access Control List) 

ZooKeeper 的权限管理亦即ACL 控制功能,使用ACL来对Znode进行访问控制。ACL的实现和Unix文件访问许可很是类似:它使用许可位来对一个节点的不一样操做进行容许或禁止的权限控制。可是和标准的Unix许可不一样的是,Zookeeper对于用户类别的区分,不止局限于全部者(owner)、组 (group)、全部人(world)三个级别。Zookeeper中,数据节点没有"全部者"的概念。访问者利用id标识本身的身份,并得到与之相应的不一样的访问权限。java

ZooKeeper 的权限管理经过Server、Client 两端协调完成:node

(1) Server端 算法

一个ZooKeeper 的节点存储两部份内容:数据状态,状态中包含ACL 信息。建立一个znode 会产生一个ACL 列表,列表中每一个ACL 包括:express

权限permsapache

验证模式scheme服务器

具体内容expression:Idssession

例如,当scheme="digest" 时, Ids 为用户名密码, 即"root :J0sTy9BCUKubtK1y8pkbL7qoxSw"。ZooKeeper 提供了以下几种验证模式:ide

① Digest: Client 端由用户名密码验证,譬如user:pwd 函数

② Host: Client 端由主机名验证,譬如localhost测试

③ Ip:Client 端由IP 地址验证,譬如172.2.0.0/24

④ World :固定用户为anyone,为全部Client 端开放权限

当会话创建的时候,客户端将会进行自我验证。

权限许可集合以下:

① Create 容许对子节点Create 操做

Read 容许对本节点GetChildren 和GetData 操做

Write 容许对本节点SetData 操做

Delete 容许对子节点Delete 操做

Admin 容许对本节点setAcl 操做

另外,ZooKeeper Java API支持三种标准的用户权限,它们分别为:

ZOO_PEN_ACL_UNSAFE:对于全部的ACL来讲都是彻底开放的,任何应用程序能够在节点上执行任何操做,好比建立、列出并删除子节点。
ZOO_READ_ACL_UNSAFE:对于任意的应用程序来讲,仅仅具备读权限
ZOO_CREATOR_ALL_ACL:授予节建立者全部权限须要注意的是,设置此权限以前,建立者必须已经通了服务器的认证。

Znode ACL 权限用一个int 型数字perms 表示,perms 的5 个二进制位分别表示setacl、delete、create、write、read。好比adcwr=0x1f,----r=0x1,a-c-r=0x15。

注意的是,exists操做和getAcl操做并不受ACL许可控制,所以任何客户端能够查询节点的状态和节点的ACL。

(2) 客户端

Client 经过调用addAuthInfo()函数设置当前会话的Author信息针对Digest 验证模式。Server 收到Client 发送的操做请求existsgetAcl 以外,须要进行ACL 验证:对该请求携带的Author 明文信息加密,并与目标节点的ACL 信息进行比较,若是匹配则具备相应的权限,不然请求被Server 拒绝。

下面演示一个经过digest(用户名:密码的方式)为建立的节点设置ACL的例子,代码以下:

  1. import org.apache.Zookeeper.*;
  2. import org.apache.Zookeeper.server.auth.DigestAuthenticationProvider;
  3. import org.apache.Zookeeper.data.*;
  4. import java.util.*;
  5. public class NewDigest {
  6.     public static void main(String[] args) throws Exception {//new 一个 acl
  7.         List<ACL> acls = new ArrayList<ACL>();
  8.       //添加第一个id,采用用户名密码形式
  9.         Id id1 = new Id("digest",DigestAuthenticationProvider.generateDigest("admin:admin"));
  10.         ACL acl1 = new ACL(ZooDefs.Perms.ALL, id1);
  11.         acls.add(acl1);
  12.      // 添加第二个 id,全部用户可读权限
  13.         Id id2 = new Id("world", "anyone");
  14.         ACL acl2 = new ACL(ZooDefs.Perms.READ, id2);
  15.         acls.add(acl2);
  16.         // Zk admin认证,建立/test ZNode
  17.       ZooKeeper Zk = new ZooKeeper("host1:2181,host2:2181,host3:2181",2000, null);
  18.       Zk.addAuthInfo("digest", "admin:admin".getBytes());
  19.       Zk.create("/test", "data".getBytes(), acls, CreateMode.PERSISTENT);
  20.    }
  21. }

1.2 ZooKeeper SuperDigest

(1) 一次Client 对Znode 进行操做的验证ACL 的方式为:

a) 遍历znode的全部ACL:

对于每个ACL,首先操做类型权限(perms)匹配

只有匹配权限成功才进行session 的auth 信息与ACL 的用户名、密码匹配

b) 若是两次匹配都成功,则容许操做;不然,返回权限不够error(rc=-102)

(2) 若是Znode ACL List 中任何一个ACL 都没有setAcl 权限,那么就算superDigest 也修改不了它的权限;再假如这个Znode 还不开放delete 权限,那么它的全部子节点都将不会被删除。惟一的办法是经过手动删除snapshot 和log 的方法,将ZK 回滚到一个之前的状态,而后重启,固然这会影响到该znode 之外其它节点的正常应用。

(3) superDigest 设置的步骤:

启动ZK 的时候( zkServer.sh ) , 加入参数: Java"-Dzookeeper .DigestAuthenticationProvider.superDigest=super:D/InIHSb7yEEbrWz8b9l71RjZJU="(无空格)。

在客户端使用的时候, addAuthInfo("digest", "super:test", 10, 0, 0); " super:test" 为"super:D/InIHSb7yEEbrWz8b9l71RjZJU="的明文表示,加密算法同setAcl。

2、 Watch机制

Zookeeper客户端在数据节点上设置监视,则当数据节点发生变化时,客户端会收到提醒。ZooKeeper中的各类读请求,如getDate(),getChildren(),和exists(),均可以选择加"监视点"(watch)。"监视点"指的是一种一次性的触发器(trigger),当受监视的数据发生变化时,该触发器会通知客户端。

(1) 监视机制有三个关键点:

"监视点"是一次性的,当触发过一次以后,除非从新设置,新的数据变化不会提醒客户端。

"监视点"将数据改变的通知客户端。若是数据改变是客户端A引发的,不能保证"监视点"通知事件会在引起数据修改的函数返回前到达客户端A

对于"监视点",ZooKeeper有以下保证:客户端必定是在接收到"监视"事件(watch event)以后才接收到数据的改变信息

(2) "监视点"保留在ZooKeeper服务器上,则当客户端链接到新的ZooKeeper服务器上时,全部须要被触发的相关"监视点"都会被触发。当客户端断线后重连,与它的相关的"监视点"都会自动从新注册,这对客户端来讲是透明的。在如下状况,"监视点"会被错过:客户端B设置了关于节点A存在性的"监视点",但B断线了,在B断线过程当中节点A被建立又被删除。此时,B再连线后不知道A节点曾经被建立过。

(3) ZooKeeper的"监视"机制保证如下几点:

"监视"事件的触发顺序和事件的分发顺序一致。

客户端将先接收到"监视"事件,而后才收到新的数据

"监视"事件触发的顺序与ZooKeeper服务器上数据变化的顺序一致

(4) 关于ZooKeeper"监视"机制的注意点:

"监视点"是一次性的。

因为"监视点"是一次性的,并且,从接收到"监视"事件到设置新"监视点"是有延时的,因此客户端可能监控不到数据的全部变化。

一个监控对象,只会被相关的通知触发一次。若是一个客户端设置了关于某个数据点exists和getData的监控,则当该数据被删除的时候,只会触发"文件被删除"的

通知。

当客户端断开与服务器的链接时,客户端再也不能收到"监视"事件,直到从新得到链接。因此关于Session的信息将被发送给全部ZooKeeper服务器。因为当链接断开时收不到"监视",因此在这种状况下,模块行为须要容错方面的设计。

3、Session机制

3.1 会话概述

每一个ZooKeeper客户端的配置中都包括集合体中服务器的列表。在启动时,客户端会尝试链接到列表中的一台服务器。若是链接失败,它会尝试链接另外一台服务器,以此类推,直到成功与一台服务器创建链接或由于全部ZooKeeper服务器都不可用而失败。

图 3.1 ZooKeeper体系结构

一旦客户端与一台ZooKeeper服务器创建链接,这台服务器就会为该客户端建立一个新的会话。每一个会话都会有一个超时的时间设置,这个设置由建立会话的应用来设定。若是服务器在超时时间段内没有收到任何请求,则相应的会话会过时。一旦一个会话已通过期,就没法从新打开,而且任何与该会话相关联的短暂znode都会丢失。会话一般长期存在,并且会话过时是一种比较罕见的事件,但对应用来讲,如何处理会话过时还是很是重要的。

只要一个会话空闲超过必定时间,均可以经过客户端发送ping请求(也称为心跳)保持会话不过时。ping请求由ZooKeeper的客户端库自动发送,所以在咱们的代码中不须要考虑如何维护会话。这个时间长度的设置应当足够低,以便能档检测出服务器故障(由读超时体现),而且可以在会话超时的时间段内从新莲接到另一台服务器。

3.2 故障切换

ZooKeeper客户端能够自动地进行故障切换,切换至另外一台ZooKeeper服务器。而且关键的一点是,在另外一台服务器接替故障服务器以后,全部的会话和相关的短暂Znode仍然是有效的。在故障切换过程当中,应用程序将收到断开链接链接至服务的通知。当客户端断开链接时,观察通知将没法发送;可是当客户端成功恢复链接后,这些延迟的通知会被发送。固然,在客户端从新链接至另外一台服务器的过程当中,若是应用程序试图执行一个操做,这个操做将会失败。这充分体现了在真实的ZooKeeper应用中处理链接丢失异常的重要性。

4、ZooKeeper实例状态

(1) ZooKeeper状态

ZooKeeper对象在其生命周期中会经历几种不一样的状态。你能够在任什么时候刻经过getState()方法来查询对象的状态

public States getState()

States被定义成表明ZooKeeper对象不一样状态的枚举类型值(不论是什么枚举值,一个ZooKeeper的实例在一个时刻只能处于一种状态)。在试图与ZooKeeper服务创建链接的过程当中,一个新建的ZooKeeper实例处于CONNECTING状态。一旦创建链接,它就会进入CONNECTED状态。 

图 3.2 ZooKeeper状态转换

经过注册观察对象,使用了ZooKeeper对象的客户端能够收到状态转换通知。在进入CONNECTED状态时,观察对象会收到一个WatchedEvent通知,其中KeeperState的值是SyncConnected。

(2) Watch与ZooKeeper状态

ZooKeeper的观察对象肩负着双重责任:

能够用来得到ZooKeeper状态变化的相关通知;

能够用来得到Znode变化的相关通知。

监视ZooKeeper状态变化:可使用ZooKeeper对象默认构造函数的观察

监视Znode变化:可使用一个专用的观察对象,将其传递给适当的读操做。也能够经过读操做中的布尔标识来设定是否共享使用默认的观察。

ZooKeeper实例可能失去或从新链接ZooKeeper服务,在CONNECTED和CONNECTING状态中切换。若是链接断开,watcher获得一个Disconnected事件。学要注意的是,这些状态的迁移是由ZooKeeper实例本身发起的,若是链接断开他将自动尝试自动链接。

若是任何一个close()方法被调用,或是会话由Expired类型的KeepState提示过时时,ZooKeeper可能会转变成第三种状态CLOSED。一旦处于CLOSED状态,ZooKeeper对象将再也不是活动的了(可使用states的isActive()方法进行测试),并且不能被重用。客户端必须创建一个新的ZooKeeper实例才能从新链接到ZooKeeper服务。

若是,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
若是,您但愿更容易地发现个人新博客,不妨点击一下左下角的【关注我】。
若是,您对个人博客所讲述的内容有兴趣,请继续关注个人后续博客,我是【Sunddenly】。

本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。

相关文章
相关标签/搜索