Zookeeper学习第五期-zk机制架构

1. Zookeeper 权限管理机制架构

1.1 权限管理ACL(Access Control List)

Zookeeper针对每一个节点,都有一个权限控制列表ACL,它利用许可对一个节点的不同操作进行允许或禁止的权限控制。 Zookeeper的权限管理通过Server,client两端协调完成。 1. server 端 一个Zookeeper的节点(Znode)存储两部分内容:数据和状态,状态中包含ACL信息,创建一个ZNode会产生一个ACL列表,列表中每个ACL包括

  • 权限认证perms,有如下几种:

    • Create 允许对该节点创建子节点
    • Read 允许getChildren和GetData
    • Write 允许setData操作
    • Delete 允许Delete
    • Admin 允许对本节点setACL 另外,Zookeeper JavaAPI支持三种标准的用户权限,分别为
    • ZOO_PEN_ACLUNSAFE:完全开放 - ZOO_READ_ACLUNSAFE:只读权限
    • ZOO_CREATOR_ALL_ACL 授予创建者所有权限
  • 验证模式scheme zookeeper支持如下几种验证模式:

    • Digest:client端使用用户名密码验证。具体存储在Ids中
    • Host:Client端由主机名验证,如localhost
    • Ip:Client端由Ip地址验证
    • World:对所有用户开放权限
  • 具体内容expression:ids
    当Znode 的scheme="digest"时,Ids中存储用户名密码,即 "username:password" ZnodeACL权限使用一个int型数字perms标识,perms的5个二进制位分别表示:setAcl,delete,create,write,read.
    比如adcw=0x1f,----r=0x1,a-c-r=0x15 2.
    客户端Client通过调用addAuthInfo函数,设置当前会话的Author信息(针对Digest验证模式),Server收到Client发送的操作请求(除exists,getACL之外),会对其中的用户名密码进行验证,决定是拒绝还是继续操作。
    下面是代码实例:

    	import org.apache.Zookeeper.*; 
    	import org.apache.Zookeeper.server.auth.DigestAuthenticationProvider;  
    	import org.apache.Zookeeper.data.*;  
    	import java.util.*;  
    	public class NewDigest {  
    		public static void main(String\[\] args) throws Exception  
    		{ 
    			//new一个acl  
    			List acls = new ArrayList();       
    			//添加第一个id,采用用户名密码形式 
    			Id id1 = new Id("digest",DigestAuthenticationProvider.generateDigest("admin:admin"));  
    			ACL acl1 = new ACL(ZooDefs.Perms.ALL, id1);  
    			acls.add(acl1);     
    			//添加第二个id,所有用户可读权限 Id  
    			id2 = new Id("world", "anyone");  
    			ACL acl2 = new ACL(ZooDefs.Perms.READ, id2);  
    			acls.add(acl2); // Zk用admin认证,创建/test ZNode。      
    			ZooKeeper Zk = new ZooKeeper("host1:2181,host2:2181,host3:2181",2000, null);     		Zk.addAuthInfo("digest", "admin:admin".getBytes());      
    			Zk.create("/test", "data".getBytes(), acls, CreateMode.PERSISTENT); 
    		} 
    	} `
    

1.2 Zookeeper SuperDigest

  1. 一次client对ZNode进行操作的验证ACL的方式为:
    1. 遍历ZNode的所有ACL
    2. 对于每个ACL,首先操作类型与权限(perms)相匹配
    3. 只有匹配权限成功时,才进行session的auth信息与ACL的用户名密码匹配
    4. 如果两次都匹配成功,则允许操作,否则返回权限不够 error(rc=-102)
    5. 如果Znode ACL 中任何一个都没有setACL的权限 ,那么就算superDigest也修改不了他的权限,再加入这个Znode还不开放delete权限,那么他的所有子节点都不会被删除。
      唯一的办法就是通过手动删除snapshot和log的方法,将ZK回滚到一个以前的状态,然后重启,当然这会影响到其他节点的使用。
  2. superDigest 设置的步骤
    1. 启动Zk时,加入参数 Java “-Zookeeper。DigestAuthenticationProvider.superDigest=super:D/IniIHSb7yEEbrWz8b9l71RjZJU=”
    2. 在客户端启动的时候,addAuthInfo("digest","super:test",10,0,0);"

2. Watch机制

重温一下:Zookeeper的各种读请求,如getData getChildren和exists都可以选择添加监视点(watch),一种一次性的触发器,当监视的数据发生变化时,触发器会通知客户端。

2.1 Watch机制有三个关键点:

  1. watch是一次性的,当触发过一次后,除非再次注册watch,否则新的数据变化不会通知到客户端
  2. watch 将数据改变的通知客户端,如果数据改变是客户端A引起的,不能保证监视点通知时间会在引发数据修改的函数返回前到达客户端A
  3. 对于Watch,Zookeeper有如下保证
    • 客户端一定是在接收到Watch事件之后才会收到数据的改变通知。
    • Watch保留在Zokeeper服务器上,当客户端连接到新的Zookeeper服务器上时,所有需要触发的相关Watch都会被触发,当客户端断线后重连,与它相关的watch都会重新注册,这对于客户端是透明的。
    • 在以下情况,Watch将会被错过: 客户端B设置了关于节点A的existsWatch,但是B掉线了,在B掉线的过程中,A被创建又被删除,此时,B在连线后并不知道A曾经被创建过。

2.2 Zookeeper的Watch机制保证一下几点

  1. Watch时间的触发顺序与事件的分发顺序一致
  2. 客户端将先收到Watch事件,然后才收到新的数据
  3. Watch时间的触发顺序与Zookeeper上的的数据变化顺序一致。
  4. 关于Zookeeper Watch机制的注意点:
  5. Watch是一次性的
  6. 由于Watch是一次性的,而且从事件触发到设置新Watch是有延迟的,所以客户端可能监控不到数据的所有变化。
  7. 一个Watcher只会被相关的通知触发一次,如果某个客户端设置了关于某个数据点的exists和getData的Watch,则当该数据被删除时,只会触发“文件被删除”的事件
  8. 当客户端断开与服务器的连接时,无法获取Watch事件,所以这种情况需要业务端进行容错设计。

3 Session机制

3.1 会话概述

  • 每个Zookeeper客户端的配置中都包括所有Zookeeper集群的服务器列表,当客户端尝试连接一台服务器失败时,会尝试另一台服务器,直至成功连接,或者所有服务器都不可用而失败。
  • 一旦客户端与一台服务器建立连接,这台服务器就会为客户端创建一个新的会话,其中会有一个超时时间,由客户端设置。
  • 如果服务器在超时时间段内没有收到任何请求,则会话过期,一旦会话过期则无法再次打开,同时与该会话关联的任何临时节点则会丢失。
  • 会话通常长期存在,过期是一种少见的现象,但是对业务端来说,如何处理会话过期仍是一件重要的事情。
    只要一个会话空闲超过一定时间,都可以通过客户端发送心跳保持会话,心跳请求由Zookeeper的客户端自动发送,所以业务端代码不用考虑如何维护会话。
    这个时间长度的设置应当足够低,以便检测出服务器故障(由读超时体现),并且能够在会话超市的时间段内重新连接另外一台服务器。

3.2 故障切换

Zookeeper客户端可以自动的进行故障切换,当一台服务器失效时,自动切换到另一台服务器,并且关键的一点是,在另一台服务器接管会话时,所有的会话和相关的短暂ZNode仍然是有效的。
在故障切换过程中,观察通知将无法发送,但是当客户端 成功恢复连接时,这些延迟的通知将会发送。

4. Zookeeper实例状态

4.1 Zookeeper状态

Zookeeper对象在其生命周期会经历几种不同的状态。
你可以在任何时候通过getState()方法查询对象的状态,States被定义成代表Zookeeper对象处于不同状态的枚举值类型(同一时刻Zookeeper的实例只处于一种状态)。
在试图与Zookeeper服务简历连接的过程中,一个新建的Zookeeper实例处于connecting状态,一旦建立连接,他就会进入CONNECTED状态。

4.2 Watch与Zookeeper状态

Zookeeper中的Watcher对象肩负着双重责任:

  1. 可以用来获得和Zookeeper状态变化的相关通知
  2. 可以用来获得ZNode变化的相关通知 监视Zookeeper状态变化:可以使用Zookeeper对象默认构造函数的Watcher
    监听ZNode 变化:可以使用一个专用的Watcher对象,也可以设置是否共享使用默认watcher
    Zookeeper实例可能会失去或者重新连接Zookeeper服务,如果连接断开,Watcher将会得到一个Disconnected事件。

转载于:https://my.oschina.net/u/3779759/blog/2254638

你可能感兴趣的:(Zookeeper学习第五期-zk机制架构)