1. 设置znode节点数据(同步)
1 import org.apache.zookeeper.*; 2 import org.apache.zookeeper.data.Stat; 3 4 import java.io.IOException; 5 6 public class SetDataSync implements Watcher { 7 private static ZooKeeper zk; 8 private String path; 9 10 public static void main(String args[]) throws IOException, InterruptedException { 11 //zk will connect to zk server, asynchronized 12 zk = new ZooKeeper("192.168.179.101:2181", 5000, new SetDataSync()); 13 Thread.sleep(Integer.MAX_VALUE); 14 15 } 16 17 @Override 18 public void process(WatchedEvent event) { 19 // 连接建立后,设置给定路径的znode数据 20 if (event.getState() == Event.KeeperState.SyncConnected) { 21 // 连接刚刚建立 22 if (event.getType() == Event.EventType.None && event.getPath() == null) { 23 //创建新节点并重新设置data 24 try { 25 String path = zk.create("/node_by_java", "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT ); 26 setNodeData(path, "456"); 27 } catch (KeeperException e) { 28 e.printStackTrace(); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 35 }//process 36 37 38 //get node data 39 private void setNodeData(String path, String data) throws KeeperException, InterruptedException { 40 System.out.println("Reset znode data"); 41 //更新数据,返回节点状态 42 Stat stat; 43 stat = zk.setData(path, data.getBytes(), -1 ); 44 //读取数据,验证是否设置成功 45 byte[] update_data = zk.getData(path, false, stat); 46 System.out.println("Updated Data of " + path + "is: " + new String(update_data)); 47 } 48 49 }
核心API分析: stat = zk.setData(path, data.getBytes(), -1 );
public Stat setData(String path, byte[] data, int version) throws KeeperException, InterruptedException
参数1: 要修改哪一个znode节点
参数2: 新数据, String.getBytes()可以根据String字符串生成新的byte数组
参数3: version为正数,则修改znode数据时会先查看znode的version是否和给定的相同,如果不同则抛出异常,表示这个节点的数据版本已经不是你给我的版本,可能其他人做了变更
如果version=-1,则表示更新数据时不进行版本比对,管你是什么版本,我就是要修改
2. znode访问权限ACL(同步)
2.1 znode访问权限基础
zk集群中znode的权限模式(scheme) 有2种:
1)基于 IP
2)基于 用户名+密码 (digest)
根据访问策略的不同,授权对象(ID) , 也就是哪些人能访问znode节点,有不同的形式
1)IP模式下, 授权对象,是具体的IP地址
2)digest模式下,授权对象,是 username:Base64(SHA-1(username:password)), SHA-1是加密,Base64是编码(将二进制数据转换为可读符号)
对znode可以进行的操作,就是权限(permission), zk提供了5种权限:
CREATE, DELETE, READ, WRITE, ADMIN
注:单个权限(有某个), 完全权限(所有), 复合权限(2项或多项)
权限组合 = 权限模式 + 授权对象 + 权限
2.2 zk框架提供的权限控制类ACL
ACL类具有2个属性:
* perm -- int类型,就是permission
* id -- ID类型,含有String scheme, String id ( 授权模式 + 授权对象)
public void process(WatchedEvent event) { // if (event.getState() == Event.KeeperState.SyncConnected) { // 连接刚刚建立 if (event.getType() == Event.EventType.None && event.getPath() == null) { //创建新节点, 并设置节点ACL权限 try { // perms + id // id = scheme, id
// perms = 读写复合权限, 基于IP地址授权 ACL acl1 = new ACL(ZooDefs.Perms.READ| ZooDefs.Perms.WRITE, new Id("ip", "192.168.179.100")); //基于IP的访问权限,ACL(perm,id(scheme,id)) ACL acl2 = null; try {
// perms = 读写复合权限,基于digest方式授权,通过框架提供的方法自动生成:username:Base64(SHA-1(username:password)) acl2 = new ACL(ZooDefs.Perms.READ| ZooDefs.Perms.WRITE, new Id("digest", DigestAuthenticationProvider.generateDigest("shayzhang:1234"))); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } ArrayList<ACL> acls = new ArrayList<ACL>(); acls.add(acl1); acls.add(acl2); // 创建znode,并设置ACL String path = zk.create("/node_by_java", "123".getBytes(), acls, CreateMode.PERSISTENT );
// 提供认证信息给zk, 通过认证后操作节点
zk.addAuthInfo("digest", "shayzhang:1234".getBytes());
}//process
zk框架提供的ACL:
* ZooDefs.Ids.OPEN_ACL_UNSAFE 任何人可以进行任何操作
* ZooDefs.Ids.READ_ACL_UNSAFE 任何人可读
* ZooDefs.Ids.READ_ACL_UNSAFE 配合addAuthInfo使用,将前者作为节点的授权