一、ZooKeeper 原生API
ZooKeeper API分为同步操作和异步操作,包括以下操作:
创建会话
创建节点
删除节点
读取数据、子节点
更新数据
检测节点是否存在
权限控制
1、创建会话
ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
示例:
public class ZooKeeper_Constructor_Usage_Simple implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
public static void main(String[] args) throws Exception{
ZooKeeper zookeeper = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //sessionTimeout
new ZooKeeper_Constructor_Usage_Simple());//自身实现watcher接口
System.out.println(zookeeper.getState());//connecting状态
try {
connectedSemaphore.await();//等待连接成功
} catch (InterruptedException e) {}
System.out.println("ZooKeeper session established.");
}
//链接添加监视器,观察连接成功状态
public void process(WatchedEvent event) {
System.out.println("Receive watched event:" + event);
if (KeeperState.SyncConnected == event.getState()) {
connectedSemaphore.countDown();
}
}
}
利用sessionId ,复用连接
public class ZooKeeper_Constructor_Usage_With_SID_PASSWD implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
public static void main(String[] args) throws Exception{
ZooKeeper zookeeper = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new ZooKeeper_Constructor_Usage_With_SID_PASSWD());
connectedSemaphore.await();
long sessionId = zookeeper.getSessionId();
byte[] passwd = zookeeper.getSessionPasswd();
//Use illegal sessionId and sessionPassWd
zookeeper = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new ZooKeeper_Constructor_Usage_With_SID_PASSWD(),//
1l,//非法的会话id,连接失败
"test".getBytes());
//Use correct sessionId and sessionPassWd
//复用会话
zookeeper = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new ZooKeeper_Constructor_Usage_With_SID_PASSWD(),//
sessionId,//
passwd);
Thread.sleep( Integer.MAX_VALUE );
}
public void process(WatchedEvent event) {
System.out.println("Receive watched event:" + event);
if (KeeperState.SyncConnected == event.getState()) {
connectedSemaphore.countDown();
}
}
}
2、创建节点
同步方法创建节点
public class ZooKeeper_Create_API_Sync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
public static void main(String[] args) throws Exception{
ZooKeeper zookeeper = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new ZooKeeper_Create_API_Sync_Usage());
connectedSemaphore.await();
String path1 = zookeeper.create("/zk-test-ephemeral-",
"".getBytes(),
Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
System.out.println("Success create znode: " + path1);
String path2 = zookeeper.create("/zk-test-ephemeral-",
"".getBytes(), //data
Ids.OPEN_ACL_UNSAFE,//ACL控制
CreateMode.EPHEMERAL_SEQUENTIAL);//mode
System.out.println("Success create znode: " + path2);
}
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
connectedSemaphore.countDown();
}
}
}
ZooKeeper有四种形式的目录节点,即四种CreateMode,两大类,持久化节点与临时节点,自动编号节点与非自动编号节点,两两组合,分别如下:
1、PERSISTENT
持久化目录节点,存储的数据不会丢失。
2、PERSISTENT_SEQUENTIAL
顺序自动编号的持久化目录节点,存储的数据不会丢失,并且根据当前已近存在的节点数自动加 1,然后返回给客户端已经成功创建的目录节点名。
3、EPHEMERAL
临时目录节点,一旦创建这个节点的客户端与服务器端口也就是session 超时,这种节点会被自动删除。
4、EPHEMERAL_SEQUENTIAL
临时自动编号节点,一旦创建这个节点的客户端与服务器端口也就是session 超时,这种节点会被自动删除,并且根据当前已近存在的节点数自动加 1,然后返回给客户端已经成功创建的目录节点名。
ZooKeeper 客户端有3种标准的ACL:
struct ACL_vector ZOO_OPEN_ACL_UNSAFE; //(ZOO_PERM_ALL,ZOO_ANYONE_ID_UNSAFE)
struct ACL_vector ZOO_READ_ACL_UNSAFE;// (ZOO_PERM_READ, ZOO_ANYONE_ID_UNSAFE)
struct ACL_vector ZOO_CREATOR_ALL_ACL; //(ZOO_PERM_ALL,ZOO_AUTH_IDS)
ZOO_OPEN_ACL_UNSAFE使所有ACL都“开放”了:任何应用程序在节点上可进行任何操作,能创建、列出和删除它的子节点。对任何应用程序,
ZOO_READ_ACL_UNSAFE是只读的。
CREATE_ALL_ACL赋予了节点的创建者所有的权限,在创建者采用此ACL创建节点之前,已经被服务器所认证。
异步方法创建节点
public class ZooKeeper_Create_API_ASync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
public static void main(String[] args) throws Exception{
ZooKeeper zookeeper = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new ZooKeeper_Create_API_ASync_Usage());
connectedSemaphore.await();
zookeeper.create("/zk-test-ephemeral-", "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,
new IStringCallback(), "I am context."); //ctx上下文作为回调的入参,I am context
zookeeper.create("/zk-test-ephemeral-", "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,
new IStringCallback(), "I am context.");
zookeeper.create("/zk-test-ephemeral-", "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,
new IStringCallback(), "I am context.");
Thread.sleep( Integer.MAX_VALUE );
}
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
connectedSemaphore.countDown();
}
}
}
//异步回调类
class IStringCallback implements AsyncCallback.StringCallback{
public void processResult(int rc, String path, Object ctx, String name) {
System.out.println("Create path result: [" + rc + ", " + path + ", "
+ ctx + ", real path name: " + name);
}
}
rc : result code,服务器响应码,0接口调用成功(OK),-4客户端和服务端连接断开(ConnectionLoss),-110指定节点已经存在(NodeExists),-112会话已过期(SessionExpired)
path : 我们传给create的path参数值。
ctx : 我们传给create的上下文参数。
name : 创建的znode节点名称。
AsyncCallback异步callback,根据操作类型的不同,也分几类:
•StringCallback
•VoidCallback
•StatCallback
•DataCallback (getData请求)
•ChildrenCallback
•Children2Callback
3、删除节点
public class Delete_API_Sync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk;
public static void main(String[] args) throws Exception {
String path = "/zk-book";
zk = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new Delete_API_Sync_Usage());
connectedSemaphore.await();
zk.create( path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL );
zk.delete( path, -1 );//不设置默认监视器
Thread.sleep( Integer.MAX_VALUE );
}
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
}
}
}
}
4、读取数据、子节点
同步读取数据
public class GetData_API_Sync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk = null;
private static Stat stat = new Stat();
public static void main(String[] args) throws Exception {
String path = "/zk-book";
zk = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new GetData_API_Sync_Usage());
connectedSemaphore.await();
zk.create( path, "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL );
//true,这里注册了上下文默认watcher,更新data之后收到通知。stat接收状态信息
System.out.println(new String(zk.getData( path, true, stat )));
System.out.println(stat.getCzxid()+","+stat.getMzxid()+","+stat.getVersion());
zk.setData( path, "123".getBytes(), -1 );//无视事务id更新数据
Thread.sleep( Integer.MAX_VALUE );
}
//分别设置连接成功和data更新的事件处理
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
} else if (event.getType() == EventType.NodeDataChanged) {
try {//setData之后,检测到EventType.NodeDataChanged事件
System.out.println(new String(zk.getData( event.getPath(), true, stat )));
System.out.println(stat.getCzxid()+","+
stat.getMzxid()+","+
stat.getVersion());
} catch (Exception e) {}
}
}
}
}
异步读取数据,适用读取大量数据,异步获取避免影响主任务
public class GetData_API_ASync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk;
public static void main(String[] args) throws Exception {
String path = "/zk-book";
zk = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new GetData_API_ASync_Usage());
connectedSemaphore.await();
zk.create( path, "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL );
zk.getData( path, true, new IDataCallback(), null );//不直接拿到data数据,由IDataCallback异步获取
zk.setData( path, "123".getBytes(), -1 );
Thread.sleep( Integer.MAX_VALUE );
}
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
} else if (event.getType() == EventType.NodeDataChanged) {
try {
zk.getData( event.getPath(), true, new IDataCallback(), null );//检测节点变化,也用DataCallback异步获取
} catch (Exception e) {}
}
}
}
}
//DataCallback
class IDataCallback implements AsyncCallback.DataCallback{
public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
System.out.println(rc + ", " + path + ", " + new String(data));
System.out.println(stat.getCzxid()+","+
stat.getMzxid()+","+
stat.getVersion());
}
}
同步获取子节点
public class ZooKeeper_GetChildren_API_Sync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk = null;
public static void main(String[] args) throws Exception{
String path = "/zk-book";
zk = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new ZooKeeper_GetChildren_API_Sync_Usage());
connectedSemaphore.await();
zk.create(path, "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(path+"/c1", "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
List childrenList = zk.getChildren(path, true);//默认watcher,增加c2节点,收到NodeChildrenChanged通知
System.out.println(childrenList);
zk.create(path+"/c2", "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
Thread.sleep( Integer.MAX_VALUE );
}
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
} else if (event.getType() == EventType.NodeChildrenChanged) {
try {
System.out.println("ReGet Child:"+zk.getChildren(event.getPath(),true));
} catch (Exception e) {}
}
}
}
}
异步获取子节点
public class ZooKeeper_GetChildren_API_ASync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk = null;
public static void main(String[] args) throws Exception{
String path = "/zk-book";
zk = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new ZooKeeper_GetChildren_API_ASync_Usage());
connectedSemaphore.await();
zk.create(path, "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create(path+"/c1", "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zk.getChildren(path, true, new IChildren2Callback(), null);//异步通过IChildren2Callback获取节点。
//默认watcher,增加c2节点,收到NodeChildrenChanged通知
zk.create(path+"/c2", "".getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
Thread.sleep( Integer.MAX_VALUE );
}
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
} else if (event.getType() == EventType.NodeChildrenChanged) {
try {
System.out.println("ReGet Child:"+ zk.getChildren(path, true, new IChildren2Callback(), null));
} catch (Exception e) {}
}
}
}
}
//Children2Callback,不同的callback,参数不同
class IChildren2Callback implements AsyncCallback.Children2Callback{
public void processResult(int rc, String path, Object ctx, List children, Stat stat) {
System.out.println("Get Children znode result: [response code: " + rc + ", param path: " + path
+ ", ctx: " + ctx + ", children list: " + children + ", stat: " + stat);
}
}
5、更新数据
同步更新数据
public class SetData_API_Sync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk;
public static void main(String[] args) throws Exception {
String path = "/zk-book";
zk = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new SetData_API_Sync_Usage());
connectedSemaphore.await();
zk.create( path, "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL );
zk.getData( path, true, null );
Stat stat = zk.setData( path, "456".getBytes(), -1 );//-1。基于最新的版本更新操作,或者对于更新操作无原子性要求
System.out.println(stat.getCzxid()+","+
stat.getMzxid()+","+
stat.getVersion());
Stat stat2 = zk.setData( path, "456".getBytes(), stat.getVersion() );
System.out.println(stat2.getCzxid()+","+
stat2.getMzxid()+","+
stat2.getVersion());
try {
zk.setData( path, "456".getBytes(), stat.getVersion() );
} catch ( KeeperException e ) {
System.out.println("Error: " + e.code() + "," + e.getMessage());//更新失败
}
Thread.sleep( Integer.MAX_VALUE );
}
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
}
}
}
}
异步更新数据
public class SetData_API_ASync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk;
public static void main(String[] args) throws Exception {
String path = "/zk-book";
zk = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new SetData_API_ASync_Usage());
connectedSemaphore.await();
zk.create( path, "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL );
zk.setData( path, "456".getBytes(), -1, new IStatCallback(), null );
Thread.sleep( Integer.MAX_VALUE );
}
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
}
}
}
}
//StatCallback
class IStatCallback implements AsyncCallback.StatCallback{
public void processResult(int rc, String path, Object ctx, Stat stat) {
if (rc == 0) {
System.out.println("SUCCESS");
}
}
}
6、检测节点是否存在
public class Exist_API_Sync_Usage implements Watcher {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk;
public static void main(String[] args) throws Exception {
String path = "/zk-book";
zk = new ZooKeeper("domain1.book.zookeeper:2181",
5000, //
new Exist_API_Sync_Usage());
connectedSemaphore.await();
zk.exists( path, true );//还没创建的节点,仍能监听
zk.create( path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT );
zk.setData( path, "123".getBytes(), -1 );
zk.create( path+"/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT );//子节点变化不会通知
zk.delete( path+"/c1", -1 );
zk.delete( path, -1 );
Thread.sleep( Integer.MAX_VALUE );
}
@Override
public void process(WatchedEvent event) {
try {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
} else if (EventType.NodeCreated == event.getType()) {
System.out.println("Node(" + event.getPath() + ")Created");
zk.exists( event.getPath(), true );
} else if (EventType.NodeDeleted == event.getType()) {
System.out.println("Node(" + event.getPath() + ")Deleted");
zk.exists( event.getPath(), true );
} else if (EventType.NodeDataChanged == event.getType()) {
System.out.println("Node(" + event.getPath() + ")DataChanged");
zk.exists( event.getPath(), true );
}
}
} catch (Exception e) {}
}
}
7、权限控制
使用无权限会话,或者错误权限会话,访问有权限的节点数据会失败
public class AuthSample_Get2 {
final static String PATH = "/zk-book-auth_test";
public static void main(String[] args) throws Exception {
ZooKeeper zookeeper1 = new ZooKeeper("domain1.book.zookeeper:2181",5000,null);
zookeeper1.addAuthInfo("digest", "foo:true".getBytes());
zookeeper1.create( PATH, "init".getBytes(), //
Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL );
ZooKeeper zookeeper2 = new ZooKeeper("domain1.book.zookeeper:2181",50000,null);
zookeeper2.addAuthInfo("digest", "foo:true".getBytes());
System.out.println(zookeeper2.getData( PATH, false, null ));
ZooKeeper zookeeper3 = new ZooKeeper("domain1.book.zookeeper:2181",50000,null);
zookeeper3.addAuthInfo("digest", "foo:false".getBytes());
zookeeper3.getData( PATH, false, null );
}
}
删除节点的权限控制,删除子节点需权限,删除节点本身不需要权限
public class AuthSample_Delete {
final static String PATH = "/zk-book-auth_test";
final static String PATH2 = "/zk-book-auth_test/child";
public static void main(String[] args) throws Exception {
ZooKeeper zookeeper1 = new ZooKeeper("domain1.book.zookeeper:2181",5000,null);
zookeeper1.addAuthInfo("digest", "foo:true".getBytes());
zookeeper1.create( PATH, "init".getBytes(), Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT );
zookeeper1.create( PATH2, "init".getBytes(), Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL );
try {
ZooKeeper zookeeper2 = new ZooKeeper("domain1.book.zookeeper:2181",50000,null);
zookeeper2.delete( PATH2, -1 );
} catch ( Exception e ) {
System.out.println( "删除节点失败: " + e.getMessage() );
}
ZooKeeper zookeeper3 = new ZooKeeper("domain1.book.zookeeper:2181",50000,null);
zookeeper3.addAuthInfo("digest", "foo:true".getBytes());
zookeeper3.delete( PATH2, -1 );
System.out.println( "成功删除节点:" + PATH2 );
ZooKeeper zookeeper4 = new ZooKeeper("domain1.book.zookeeper:2181",50000,null);
zookeeper4.delete( PATH, -1 );
System.out.println( "成功删除节点:" + PATH );
}
}