一:Zookeeper使用

 

    1.客户端脚本使用

    主要命令如下:

删除zookeeper节点下 某一个数据 zookeeper删除节点命令_zookeeper

 

        1)打开客户端

./zkCli.sh --会默认连接本地2181端口
./zkCli.sh -server ip:port --打开指定IP:port

        2)添加节点

create [-s] [-e] path data
create /zk_test 111 --创建根节点/下子节点 zk_test 值为111

        3)修改节点值

set path data [version]
set /zk_test 121 --修改/zk_test 值为121

       

  4)查看节点

ls path [watch]
ls /zk_test --查看/zk_test的值
ls / --查看根节点下所有节点

        5)删除节点

delete path [version]
delete /zk_test --删除/zk_test节点

 

 

 

        注意:如果该节点下有子节点,则不能删除该节点,需要先删除子节点

 

    使用JavaAPI前提条件:本人使用zookeeper3.4.11,maven管理,pom.xml如下

<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
		<dependency>
		    <groupId>org.apache.zookeeper</groupId>
		    <artifactId>zookeeper</artifactId>
		    <version>3.4.11</version>
		</dependency>
				
		<dependency>  
            <groupId>log4j</groupId>  
            <artifactId>log4j</artifactId>  
            <version>1.2.15</version>  
            <exclusions>  
                <exclusion>  
                    <groupId>javax.jms</groupId>  
                    <artifactId>jms</artifactId>  
                </exclusion>  
                <exclusion>  
                    <groupId>com.sun.jdmk</groupId>  
                    <artifactId>jmxtools</artifactId>  
                </exclusion>  
                <exclusion>  
                    <groupId>com.sun.jmx</groupId>  
                    <artifactId>jmxri</artifactId>  
                </exclusion>  
            </exclusions>  
        </dependency>

   由于jmxtools相关jar包需要认证,就直接exclude,用户也可以单独下载之后放到m2

 

    2.创建ZooKeeper客户端(JavaAPI)

        构造方法如下:

ZooKeeper(java.lang.String connectString, int sessionTimeout, Watcher watcher)
    To create a ZooKeeper client object, the application needs to pass a connection string containing a comma separated list of host:port pairs, each corresponding to a ZooKeeper server.
        
ZooKeeper(java.lang.String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly)
    To create a ZooKeeper client object, the application needs to pass a connection string containing a comma separated list of host:port pairs, each corresponding to a ZooKeeper server.
        
ZooKeeper(java.lang.String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd)
    To create a ZooKeeper client object, the application needs to pass a connection string containing a comma separated list of host:port pairs, each corresponding to a ZooKeeper server.
        
ZooKeeper(java.lang.String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd, boolean canBeReadOnly)
    To create a ZooKeeper client object, the application needs to pass a connection string containing a comma separated list of host:port pairs, each corresponding to a ZooKeeper server.

 

 

        * Watch 是一个监控器,用于监控zookeeper状态变化,当状态变化时,会回调相关方法

        * sessionID和sessionPasswd 分别代表会话ID和会话秘钥,这两个参数能够确定一个会话

 

        使用方式如下:(写成简单单例方式来用)

public class ZookeeperInstance {

	private static ZooKeeper zookeeper = null;
	public static final String CONNECT_STRING = "localhost:2181";
	public static final int SESSION_TIME_OUT = 5000;
	static CountDownLatch cdl = new CountDownLatch(1);
	
	public static ZooKeeper getInstance(){
		if(null == zookeeper){
			try {
				zookeeper = new ZooKeeper(CONNECT_STRING, SESSION_TIME_OUT, new ZookeeperWatcher());
				//由于zookeeper的创建是异步的,直接返回的并不是可用的zookeeper,状态也是States.CONNECTING,真正连接成功后状态变为CONNECTED
				cdl.await();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return zookeeper;
	}
    //异步处理类,当状态变化时,会回调process方法
	static class ZookeeperWatcher implements Watcher{
		@Override
		public void process(WatchedEvent event) {

			System.out.println("receive watched event:" + event);
			if(KeeperState.SyncConnected == event.getState()){
				cdl.countDown();
			}
		}
	}
}

       注意:zookeeper的创建是异步的,

 

 

    3.创建zookeeper节点(JavaAPI)

        方法如下所示:

java.lang.String	create(java.lang.String path, byte[] data, java.util.List<ACL> acl, CreateMode createMode)
    Create a node with the given path.
    
void	create(java.lang.String path, byte[] data, java.util.List<ACL> acl, CreateMode createMode, AsyncCallback.StringCallback cb, java.lang.Object ctx)
    The asynchronous version of create.

 

        * path 节点的路径

        * data 节点的初始值

OPEN_ACL_UNSAFE, CREATOR_ALL_ACL, READ_ACL_UNSAFE

        * createMode 节点的创建策略 (用户可使用 CreateMode下的值,可选项有PERSISTENT ,PERSISTENT_SEQUENTIAL, EPHEMERAL,EPHEMERAL_SEQUENTIAL )

            PERSISTENT意味持久化节点,客户端断开连接后,节点依旧存在

            EPHEMERAL临时节点,客户端断开连接后,节点就删除

            SEQUENTIAL会在节点path后加上一个顺序码

 

         使用方式如下:

        1)同步创建
 

//1.同步方式创建节点
//1.1 CreateMode.EPHEMERAL 临时节点 在客户端断开的时候断开连接
String path1 = zookeeper.create("/z_test_e", "111".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println(path1);
String path2 = zookeeper.create("/z_test_e_s", "222".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(path2);

//1.2 CreateMode.PERSISTENT 持久化节点 
String path3 = zookeeper.create("/z_test_p", "111".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(path3);
String path4 = zookeeper.create("/z_test_p_s", "222".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
System.out.println(path4);

       2)异步创建

//2.异步方式创建节点
zookeeper.create("/z_test_asyn_p_", "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, new StringCallbackImpl(), "i am context");
zookeeper.create("/z_test_asyn_p_s", "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL, new StringCallbackImpl(), "i am context");
try {
	Thread.sleep(10000);//这个需要加上,因为创建节点是异步操作,
} catch (InterruptedException e) {
	e.printStackTrace();
}

static class StringCallbackImpl implements AsyncCallback.StringCallback{
	@Override
	public void processResult(int rc, String path, Object ctx, String name) {

		System.out.println("create path result:" + rc + "," + path + "," + ctx + ",real name :" + name);
	}
}

        注意:由于此时的节点是异步创建,所以需要在最后的时候加上sleep,如果直接结束,节点有可能还没创建成功

org.apache.zookeeper.KeeperException.Code,0代表成功)

 

    4.修改zookeeper节点值(JavaAPI)

        方法如下所示:

Stat	setData(java.lang.String path, byte[] data, int version)
    Set the data for the node of the given path if such a node exists and the given version matches the version of the node (if the given version is -1, it matches any node's versions).
                                                                                                                             
void	setData(java.lang.String path, byte[] data, int version, AsyncCallback.StatCallback cb, java.lang.Object ctx)
    The asynchronous version of setData.

        使用方式如下:

Stat stat = zookeeper.setData("/z_test_p", "112211".getBytes(), 3);
System.out.println("setData res:" + stat);

zookeeper.setData("/z_test_p", "1111".getBytes(), 4, new AsyncCallback.StatCallback() {
	@Override
	public void processResult(int rc, String path, Object ctx, Stat stat) {
		System.out.println("setData res:" + stat);
	}
}, "setData");

Thread.sleep(10000);

 

注意:一定要设置正确的version,如果该version不存在,则会报错;version=-1匹配节点所有的version

 

 

    5.查看子节点(JavaAPI)

        方法如下所示:

java.util.List<java.lang.String>	getChildren(java.lang.String path, boolean watch)
    Return the list of the children of the node of the given path.
    
void	getChildren(java.lang.String path, boolean watch, AsyncCallback.Children2Callback cb, java.lang.Object ctx)
    The asynchronous version of getChildren.
    
void	getChildren(java.lang.String path, boolean watch, AsyncCallback.ChildrenCallback cb, java.lang.Object ctx)
    The asynchronous version of getChildren.
    
java.util.List<java.lang.String>	getChildren(java.lang.String path, boolean watch, Stat stat)
    For the given znode path return the stat and children list.
    
java.util.List<java.lang.String>	getChildren(java.lang.String path, Watcher watcher)
    Return the list of the children of the node of the given path.
    
void	getChildren(java.lang.String path, Watcher watcher, AsyncCallback.Children2Callback cb, java.lang.Object ctx)
    The asynchronous version of getChildren.
    
void	getChildren(java.lang.String path, Watcher watcher, AsyncCallback.ChildrenCallback cb, java.lang.Object ctx)
    The asynchronous version of getChildren.
    
java.util.List<java.lang.String>	getChildren(java.lang.String path, Watcher watcher, Stat stat)
    For the given znode path return the stat and children list.

        使用方式如下:

//同步
List<String> children = zookeeper.getChildren("/", true);
System.out.println(Arrays.toString(children.toArray()));

//异步
zookeeper.getChildren("/", true, new AsyncCallback.Children2Callback() {
	@Override
	public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
		System.out.println("children:"+children);
	}
}, "getChildren");

Thread.sleep(10000);

       注意:用户可自定义实现Children2Callback接口,用于监控当前节点的子节点变化,如有变化,会回调processResult方法

 

 

    6.查看节点值(JavaAPI)

        方法如下所示:

void	getData(java.lang.String path, boolean watch, AsyncCallback.DataCallback cb, java.lang.Object ctx)
    The asynchronous version of getData.
    
byte[]	getData(java.lang.String path, boolean watch, Stat stat)
    Return the data and the stat of the node of the given path.
    
void	getData(java.lang.String path, Watcher watcher, AsyncCallback.DataCallback cb, java.lang.Object ctx)
    The asynchronous version of getData.
    
byte[]	getData(java.lang.String path, Watcher watcher, Stat stat)
    Return the data and the stat of the node of the given path.

        使用方式如下所示:

//同步
byte[] data = zookeeper.getData("/z_test_p", true, new Stat());
System.out.println(new String(data));

//异步
zookeeper.getData("/z_test_p", true, new AsyncCallback.DataCallback() {
	@Override
	public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
		System.out.println("data:" + new String(data) + ",[" + stat +"]");
	}
}, "getData");

Thread.sleep(10000);

    注意:用户可自定义实现DataCallback接口,用户监控当前节点的值变化

 

 

     7.删除节点(JavaAPI)

        方法如下所示:

void	delete(java.lang.String path, int version)
    Delete the node with the given path.
    
void	delete(java.lang.String path, int version, AsyncCallback.VoidCallback cb, java.lang.Object ctx)
    The asynchronous version of delete.

        使用方式如下

//直接删除
zookeeper.delete("/z_test_asyn_p_", 0);

//异步删除
zookeeper.delete("/z_test_e", 0, new AsyncCallback.VoidCallback() {
	@Override
	public void processResult(int rc, String path, Object ctx) {
		System.out.println("delete path result:" + rc + "," + path + "," + ctx );
	}
}, "delete this path");

Thread.sleep(10000);

        注意:只允许删除叶子节点,如果当前节点还有子节点,则无法删除 

    8.权限认证

        添加权限方法如下:

void	addAuthInfo(java.lang.String scheme, byte[] auth)
    Add the specified scheme:auth information to this connection.

        schema权限模式有:

        * ip (针对某个特定的IP)

        * digest (常用模式,形如 username:password)

        * world (开放模式,对所有用户开放)

        * super (超级管理员模式,可以对任何节点进行操作)

 

        使用方式如下:

String path ="/act1";
CountDownLatch cdl = new CountDownLatch(1);
try {
	//给当前zookeeper客户端添加权限
	zookeeper.addAuthInfo("digest", "zhangsan:123".getBytes());//用户注册模式
	zookeeper.create(path, "data".getBytes(), Ids.CREATOR_ACL_UNSAFE, CreateMode.PERSISTENT, new AsyncCallback.StringCallback() {
		@Override
		public void processResult(int rc, String path, Object ctx, String name) {
			System.out.println("create path result:" + rc + "," + path + "," + ctx + ",real name :" + name);					
			cdl.countDown();
		}
	}, "createNode");
	cdl.await();
}
ommit ...

        这样创建出的的节点/act1就除了zhangsan的其他普通用户(admin除外)就无法进行访问

        注意:ACL需要是 CREATOR_ACL_UNSAFE,表示只有该创建者拥有增删改查权限

 

        下面用其他客户端访问

//重新获取客户端,定义为其他用户名密码
ZooKeeper zookeeper1 = new ZooKeeper(ZookeeperInstance.CONNECT_STRING, ZookeeperInstance.SESSION_TIME_OUT, new ZookeeperWatcher());
zookeeper1.addAuthInfo("digest", "lisi:321".getBytes());
Thread.sleep(3000);
//用其他账户来读取/act数据
byte[] data = zookeeper1.getData(path, true, null);
System.out.println(new String(data));

        会报错,KeeperErrorCode = NoAuth for /act1




参考:

从Paxos到Zookeeper  分布式一致性原理与实践(倪超)

zookeeper3.4.11 API