- 节点类型
- 持久节点(PERSISTENT)
- 持久顺序节点(PERSISTENT_SEQUENTIAL)
- 临时节点(EPHEMERAL)
- 临时顺序节点(EPHEMERAL_SEQUENTIAL)
create -e 临时 -s 顺序
- acl
CREATE:表示创建子节点的权限
READ:表示获取节点数据和子节点列表的权限
WRITE:表示更新节点数据的权限
DELETE:表示删除子节点的权限
ADMIN:表示设置节点ACL的权限
1> digest
语法:digest:username:BASE64(SHA1(password)):cdrwa
digest:是授权方式
username:BASE64(SHA1(password)):是id部分
cdrwa:权限部份
用户名+密码授权访问方式,也是常用的一种授权策略。id部份是用户名和密码做sha1加密再做BASE64加密后的组合,比如设置一个节点的用户名为yangxin,密码为123456,则表示方式为:yangxin:BASE64(SHA1(123456))
⇒ yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=
。密码加密需要用到zk的一个工具类来生成,如下所示:
shell> java -jar zookeeper/zookeeper-3.4.9.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider yangxin:123456
yangxin:123456->yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=
下面是演示创建节点,并添加授权信息操作节点的示例:
## 创建节点/node_05
shell> create /node_05 data
Created /node_05
## 设置权限
shell> setAcl /node_05 digest:yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=:cdrwa
cZxid = 0x8e
ctime = Mon Nov 14 21:38:52 CST 2016
mZxid = 0x8e
mtime = Mon Nov 14 21:38:52 CST 2016
pZxid = 0x8e
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
## 获取节点刚刚设置的权限
shell> getAcl /node_05
'digest,'yangxin:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=
: cdrwa
## 没有授权,创建节点失败
shell> create /node_05/node_05_01 data
Authentication is not valid : /node_05/node_05_01
## 添加授权信息
shell> addauth digest yangxin:123456
## 添加授权信息后,就可以正常操作了
shell> create /node_05/node_05_01 data
Created /node_05/node_05_01
2> ip
基于客户端IP地址校验,限制只允许指定的客户端能操作znode。
比如,设置某个节点只允许IP为192.168.1.100
的客户端能读写该写节点的数据:ip:192.168.1.100:rw
shell> setAcl /node_08 ip:192.168.1.100:rw
3> world
语法:world:anyone:cdrwa
创建节点默认的scheme,所有人都可以访问。如下所示:
shell> create /node_06 data
Created /node_06
shell> getAcl /node_06
'world,'anyone
: cdrwa
4> super
添加方式:
只能在启动服务器的时候添加。
假设这个超管是:super:admin,通过代码得到其哈希值:
String m = DigestAuthenticationProvider.generateDigest("super:admin");
super:xQJmxLMiHGwaqBvst5y6rkB6HQs=
这就是脚本中启动zk的命令,默认只有以上两个配置项,我们需要加一个超管的配置项:
-Dzookeeper.DigestAuthenticationProvider.superDigest=admin:015uTByzA4zSglcmseJsxTo7n3c=
之后启动zk集群,输入如下命令添加权限:addauth digest super:admin
package com.aicong.test.helloZookeeper;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Perms;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.server.auth.DigestAuthenticationProvider;
public class CreateNodeSyncAuth implements Watcher {
private static ZooKeeper zookeeper;
private static boolean somethingDone = false;
public static void main(String[] args) throws IOException, InterruptedException {
zookeeper = new ZooKeeper("112.74.219.174:2181",5000,new CreateNodeSyncAuth());
System.out.println(zookeeper.getState());
Thread.sleep(Integer.MAX_VALUE);
}
/*
* 权限模式(scheme): ip, digest
* 授权对象(ID)
* ip权限模式: 具体的ip地址
* digest权限模式: username:Base64(SHA-1(username:password))
* 权限(permission): create(C), DELETE(D),READ(R), WRITE(W), ADMIN(A)
* 注:单个权限,完全权限,复合权限
*
* 权限组合: scheme + ID + permission
*
*
*
* */
private void doSomething(){
try {
//创建节点的时候要求权限验证
//基于IP
ACL aclIp = new ACL(Perms.READ,new Id("ip","112.74.219.174"));
//基于用户名密码
ACL aclDigest = new ACL(Perms.READ|Perms.WRITE,new Id("digest",DigestAuthenticationProvider.generateDigest("jike:123456")));
ArrayList<ACL> acls = new ArrayList<ACL>();
acls.add(aclDigest);
acls.add(aclIp);
//zookeeper.addAuthInfo("digest", "jike:123456".getBytes());
String path = zookeeper.create("/node_10", "123".getBytes(), acls, CreateMode.PERSISTENT);
System.out.println("return path:"+path);
somethingDone = true;
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void process(WatchedEvent event) {
// TODO Auto-generated method stub
System.out.println("收到事件:"+event);
if (event.getState()==KeeperState.SyncConnected){
if (!somethingDone && event.getType()==EventType.None && null==event.getPath()){
doSomething();
}
}
}
}
调用方可以使用代码:
package com.aicong.test.helloZookeeper;
import java.io.IOException;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class GetDataSyncAuth implements Watcher{
private static ZooKeeper zooKeeper;
private static Stat stat = new Stat();
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
zooKeeper = new ZooKeeper("112.74.219.174:2181",5000,new GetDataSyncAuth());
System.out.println(zooKeeper.getState().toString());
Thread.sleep(Integer.MAX_VALUE);
}
private void doSomething(ZooKeeper zookeeper){
//权限验证
zooKeeper.addAuthInfo("digest", "jike:1234".getBytes());
try {
System.out.println(new String(zooKeeper.getData("/node_4", true, stat)));
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void process(WatchedEvent event) {
// TODO Auto-generated method stub
if (event.getState()==KeeperState.SyncConnected){
if (event.getType()==EventType.None && null==event.getPath()){
doSomething(zooKeeper);
}else{
if (event.getType()==EventType.NodeDataChanged){
try {
System.out.println(new String(zooKeeper.getData(event.getPath(), true, stat)));
System.out.println("stat:"+stat);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
- curator
package com.zk.dev.curator;
import java.util.List;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.api.CuratorWatcher;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
public class CuratorClientTest {
private CuratorFramework client = null;
public CuratorClientTest() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
client = CuratorFrameworkFactory.builder()
.connectString("localhost:2181,localhost:2182")
.sessionTimeoutMs(10000).retryPolicy(retryPolicy)
.namespace("base").build();
client.start();
}
public void closeClient() {
if (client != null)
this.client.close();
}
public void createNode(String path, byte[] data) throws Exception {
client.create().creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT).withACL(Ids.OPEN_ACL_UNSAFE)
.forPath(path, data);
}
public void deleteNode(String path, int version) throws Exception {
// client.delete().guaranteed().deletingChildrenIfNeeded().withVersion(version).inBackground(new
// DeleteCallBack()).forPath(path);
client.delete().guaranteed().deletingChildrenIfNeeded().withVersion(version)
.inBackground(new DeleteCallBack()).forPath(path);
}
public void readNode(String path) throws Exception {
Stat stat = new Stat();
byte[] data = client.getData().storingStatIn(stat).forPath(path);
System.out.println("读取节点" + path + "的数据:" + new String(data));
System.out.println(stat.toString());
}
public void updateNode(String path, byte[] data, int version)
throws Exception {
client.setData().withVersion(version).forPath(path, data);
}
public void getChildren(String path) throws Exception {
List<String> children = client.getChildren().usingWatcher(new WatcherTest()).forPath("/curator");
for (String pth : children) {
System.out.println("child=" + pth);
}
}
public void addNodeDataWatcher(String path) throws Exception {
final NodeCache nodeC = new NodeCache(client, path);
nodeC.start(true);
nodeC.getListenable().addListener(new NodeCacheListener() {
public void nodeChanged() throws Exception {
String data = new String(nodeC.getCurrentData().getData());
System.out.println("path=" + nodeC.getCurrentData().getPath()
+ ":data=" + data);
}
});
}
public void addChildWatcher(String path) throws Exception {
final PathChildrenCache cache = new PathChildrenCache(this.client,
path, true);
cache.start(StartMode.POST_INITIALIZED_EVENT);//ppt中需要讲StartMode
System.out.println(cache.getCurrentData().size());
//byte childone[] = cache.getCurrentData().get(0).getData();
// System.out.println("childone:"
// + cache.getCurrentData().get(0).getPath() + ";data="
// + new String(childone));
cache.getListenable().addListener(new PathChildrenCacheListener() {
public void childEvent(CuratorFramework client,
PathChildrenCacheEvent event) throws Exception {
if(event.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)){
System.out.println("客户端子节点cache初始化数据完成");
System.out.println("size="+cache.getCurrentData().size());
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){
System.out.println("添加子节点:"+event.getData().getPath());
System.out.println("修改子节点数据:"+new String(event.getData().getData()));
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){
System.out.println("删除子节点:"+event.getData().getPath());
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
System.out.println("修改子节点数据:"+event.getData().getPath());
System.out.println("修改子节点数据:"+new String(event.getData().getData()));
}
}
});
}
public class DeleteCallBack implements BackgroundCallback {
public void processResult(CuratorFramework client, CuratorEvent event)
throws Exception {
// TODO Auto-generated method stub
System.out.println(event.getPath()+",data="+event.getData());
System.out.println("event type="+event.getType());
System.out.println("event code="+event.getResultCode());
}
}
public class WatcherTest implements CuratorWatcher {
public void process(WatchedEvent event) throws Exception {
// TODO Auto-generated method stub
System.out.println(event.getPath());
}
}
public static void main(String[] args) {
CuratorClientTest ct = null;
try {
ct = new CuratorClientTest();
// ct.createNode("/curator/test10/node1", "test-node1".getBytes());
//ct.readNode("/curator/test/node1");
//ct.getChildren("/curator");
// ct.updateNode("/curator/test/node1", "test-node1-new".getBytes(),
// 0);
// ct.readNode("/curator/test/node1");
// ct.deleteNode("/curator/test10", 0);
ct.addNodeDataWatcher("/curator/test7");
ct.addChildWatcher("/curator");
Thread.sleep(300000);
} catch (Exception e) {
e.printStackTrace();
} finally {
ct.closeClient();
}
}
}