• ZooKeeper-znode概念与使用


    可以将ZK看作一个具有高可用性特征的文件系统。这个文件系统中没有文件和目录,而是统一使用节点(znode)的概念,称为znode。znode既可以作为保存数据的容器(如同文件),也可以作为保存其他znode的容器(如同目录)。所有的znode构成了一个层次化的命名空间,一种自然的建立组成员列表的方式就是利用这种层次结构,创建一个以组名为节点名的znode作为父节点,然后以组成员名(服务器名)为节点名来创建作为子节点的znode。

    创建组

    package com.zhen.zookeeper.createGroup;
    
    import java.io.IOException;
    import java.util.concurrent.CountDownLatch;
    
    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.KeeperState;
    import org.apache.zookeeper.ZooDefs.Ids;
    import org.apache.zookeeper.ZooKeeper;
    
    /**
     * @author FengZhen
     * @date 2018年10月13日
     * 创建组
     */
    public class CreateGroup implements Watcher{
    
    	private static final int SESSION_TIMEOUT = 5000;
    	
    	private ZooKeeper zk;
    	private CountDownLatch connectedSignal = new CountDownLatch(1);
    	
    	public void connect(String hosts) throws IOException, InterruptedException {
    		/**
    		 * hosts:ZooKeeper服务的主机地址(可指定端口,默认是2181)
    		 * SESSION_TIMEOUT:以毫秒为单位的会话超时参数(此处为5秒)
    		 * this:Watcher对象的实例。Watcher对象接收来自于ZooKeeper的回调,以获得各种事件的通知。
    		 */
    		zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
    		connectedSignal.await();
    	}
    	
    	/**
    	 * 当客户端已经与ZK建立连接后,Watcher的process方法会被调用
    	 * 参数是一个用于表示该连接的事件。
    	 */
    	public void process(WatchedEvent event) {
    		//连接事件
    		if (event.getState() == KeeperState.SyncConnected) {
    			/**
    			 * 通过调用CountDownLatch的countDown方法来递减它的计数器。
    			 * 锁存器(latch)被创建时带有一个值为1的计数器,用于表示在它释放所有等待线程之前需要发生的事件数。
    			 * 在调用一次countDown方法之后,计数器的值变为0,则await方法返回。
    			 */
    			connectedSignal.countDown();
    		}
    	}
    
    	public void create(String groupName) throws KeeperException, InterruptedException {
    		String path = "/" + groupName;
    		/**
    		 * 用ZK的create方法创建一个新的ZK的znode
    		 * path:路径(用字符串表示)
    		 * null:znode的内容(字节数组,此处为空值)
    		 * Ids.OPEN_ACL_UNSAFE:访问控制列表(简称ACL,此处为完全开放的ACL,允许任何客户端对znode进行读写)
    		 * CreateMode.PERSISTENT:znode类型
    		 * znode类型可以分为两种:1.短暂的(ephemeral)	2.持久的(persistent)
    		 * 创建znode的客户端断开连接时,无论客户端是明确断开还是因为任何原因而终止,短暂znode都会被ZK服务删除。持久znode不会被删除。
    		 * create方法的返回值是ZK所创建的节点路径
    		 */
    		String createdPath = zk.create(path, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    		System.out.println("Created " + createdPath);
    	}
    	
    	public void close() throws InterruptedException {
    		zk.close();
    	}
    	
    	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
    		String hosts = "localhost:2181";
    		String groupName = "zoo";
    		CreateGroup createGroup = new CreateGroup();
    		createGroup.connect(hosts);
    		createGroup.create(groupName);
    		createGroup.close();
    	}
    	
    }
    

      

    提供一个连接类

    package com.zhen.zookeeper;
    
    import java.io.IOException;
    import java.util.concurrent.CountDownLatch;
    
    import org.apache.zookeeper.WatchedEvent;
    import org.apache.zookeeper.Watcher;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.Watcher.Event.KeeperState;
    
    /**
     * @author FengZhen
     * @date 2018年10月13日
     * 等待与ZK建立连接
     */
    public class ConnectionWatcher implements Watcher{
    
    	private static final int SESSION_TIMEOUT = 5000;
    	
    	protected ZooKeeper zk;
    	private CountDownLatch connectedSignal = new CountDownLatch(1);
    	
    	public void connect(String hosts) throws IOException, InterruptedException {
    		/**
    		 * hosts:ZooKeeper服务的主机地址(可指定端口,默认是2181)
    		 * SESSION_TIMEOUT:以毫秒为单位的会话超时参数(此处为5秒)
    		 * this:Watcher对象的实例。Watcher对象接收来自于ZooKeeper的回调,以获得各种事件的通知。
    		 */
    		zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
    		connectedSignal.await();
    	}
    	
    	/**
    	 * 当客户端已经与ZK建立连接后,Watcher的process方法会被调用
    	 * 参数是一个用于表示该连接的事件。
    	 */
    	public void process(WatchedEvent event) {
    		//连接事件
    		if (event.getState() == KeeperState.SyncConnected) {
    			/**
    			 * 通过调用CountDownLatch的countDown方法来递减它的计数器。
    			 * 锁存器(latch)被创建时带有一个值为1的计数器,用于表示在它释放所有等待线程之前需要发生的事件数。
    			 * 在调用一次countDown方法之后,计数器的值变为0,则await方法返回。
    			 */
    			connectedSignal.countDown();
    		}
    	}
    	
    	public void close() throws InterruptedException {
    		zk.close();
    	}
    
    }
    

      

    加入组

    package com.zhen.zookeeper.joinGroup;
    
    import java.io.IOException;
    
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.ZooDefs.Ids;
    
    import com.zhen.zookeeper.ConnectionWatcher;
    
    /**
     * @author FengZhen
     * @date 2018年10月13日
     * 加入组-注册组成员
     */
    public class JoinGroup extends ConnectionWatcher{
    
     	public void join(String groupName, String memberName) throws KeeperException, InterruptedException {
    		String path = "/" + groupName + "/" + memberName;
    		//创建短暂znode作为组znode的子节点
    		String createdPath = zk.create(path, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    		System.out.println("Created " + createdPath);
    	}
    	
     	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
     		String hosts = "localhost:2181";
    		String groupName = "zoo";
    		String memberName = "member1";
    		JoinGroup joinGroup = new JoinGroup();
    		joinGroup.connect(hosts);
    		joinGroup.join(groupName, memberName);
    		Thread.sleep(Long.MAX_VALUE);
    	}
     	
     	
     	/**
     	 * echo dump | nc localhost 2181
    		SessionTracker dump:
    		Session Sets (3):
    		0 expire at Sat Oct 13 15:57:48 CST 2018:
    		0 expire at Sat Oct 13 15:57:50 CST 2018:
    		1 expire at Sat Oct 13 15:57:52 CST 2018:
    			0x166594274c90001
    		ephemeral nodes dump:
    		Sessions with Ephemerals (1):
    		0x166594274c90001:
    			/zoo/member1
     	 */
    }
    

      

    列出组成员

    package com.zhen.zookeeper.listGroup;
    
    import java.io.IOException;
    import java.util.List;
    
    import org.apache.zookeeper.KeeperException;
    
    import com.zhen.zookeeper.ConnectionWatcher;
    
    /**
     * @author FengZhen
     * @date 2018年10月13日
     * 列出组成员
     */
    public class ListGroup extends ConnectionWatcher{
    
    	public void list(String groupName) {
    		String path = "/" + groupName;
    		try {
    			/**
    			 * 输出一个znode的子节点列表
    			 * path:该znode的路径
    			 * false:观察标志
    			 * 如果在一个znode上设置了观察标志,那么一旦该znode的状态改变,关联的观察(Watcher)会被触发。
    			 * 虽然此处没有使用观察,但在查看一个znode的子节点时,通过设置观察可以让应用程序接收到组成员加入、退出和组被删除的有关通知
    			 */
    			List<String> children = zk.getChildren(path, false);
    			if (children.isEmpty()) {
    				System.out.printf("No members in group %s
    ", groupName);
    				System.exit(1);
    			}
    			for (String child : children) {
    				System.out.println(child);
    			}
    		} catch (KeeperException e) {
    			System.out.printf("Group %s does not exist
    ", groupName);
    			System.exit(1);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String[] args) throws IOException, InterruptedException {
    		String hosts = "localhost:2181";
    		String groupName = "zoo";
    		ListGroup listGroup = new ListGroup();
    		listGroup.connect(hosts);
    		listGroup.list(groupName);
    		listGroup.close();
    	}
    	
    	/**
    	 * 也可使用命令行工具
    	 * ./zkCli.sh -server localhost:2181 ls /zoo
    	 * Connecting to localhost:2181
    		2018-10-13 16:26:10,856 [myid:] - INFO  [main:Environment@100] - Client environment:zookeeper.version=3.4.9-1757313, built on 08/23/2016 06:50 GMT
    		2018-10-13 16:26:10,860 [myid:] - INFO  [main:Environment@100] - Client environment:host.name=192.168.1.109
    		2018-10-13 16:26:10,860 [myid:] - INFO  [main:Environment@100] - Client environment:java.version=1.8.0_162
    		2018-10-13 16:26:10,863 [myid:] - INFO  [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
    		2018-10-13 16:26:10,863 [myid:] - INFO  [main:Environment@100] - Client environment:java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre
    		2018-10-13 16:26:10,863 [myid:] - INFO  [main:Environment@100] - Client environment:java.class.path=/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../build/classes:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../build/lib/*.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/slf4j-log4j12-1.6.1.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/slf4j-api-1.6.1.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/netty-3.10.5.Final.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/log4j-1.2.16.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../lib/jline-0.9.94.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../zookeeper-3.4.9.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../src/java/lib/*.jar:/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin/../conf:
    		2018-10-13 16:26:10,863 [myid:] - INFO  [main:Environment@100] - Client environment:java.library.path=/Users/FengZhen/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.
    		2018-10-13 16:26:10,863 [myid:] - INFO  [main:Environment@100] - Client environment:java.io.tmpdir=/var/folders/tr/vc5hfpsd2c56s7m9wh93401h0000gn/T/
    		2018-10-13 16:26:10,863 [myid:] - INFO  [main:Environment@100] - Client environment:java.compiler=<NA>
    		2018-10-13 16:26:10,863 [myid:] - INFO  [main:Environment@100] - Client environment:os.name=Mac OS X
    		2018-10-13 16:26:10,864 [myid:] - INFO  [main:Environment@100] - Client environment:os.arch=x86_64
    		2018-10-13 16:26:10,864 [myid:] - INFO  [main:Environment@100] - Client environment:os.version=10.13.4
    		2018-10-13 16:26:10,864 [myid:] - INFO  [main:Environment@100] - Client environment:user.name=FengZhen
    		2018-10-13 16:26:10,864 [myid:] - INFO  [main:Environment@100] - Client environment:user.home=/Users/FengZhen
    		2018-10-13 16:26:10,864 [myid:] - INFO  [main:Environment@100] - Client environment:user.dir=/Users/FengZhen/Desktop/Hadoop/zookeeper-3.4.9/bin
    		2018-10-13 16:26:10,865 [myid:] - INFO  [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@799f7e29
    		2018-10-13 16:26:10,898 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1032] - Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181. Will not attempt to authenticate using SASL (unknown error)
    		2018-10-13 16:26:11,014 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@876] - Socket connection established to localhost/0:0:0:0:0:0:0:1:2181, initiating session
    		2018-10-13 16:26:11,024 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x166594274c90006, negotiated timeout = 30000
    		
    		WATCHER::
    		
    		WatchedEvent state:SyncConnected type:None path:null
    		[member1]
    	 */
    }
    

      

    删除组

    package com.zhen.zookeeper.deleteGroup;
    
    import java.io.IOException;
    import java.util.List;
    
    import org.apache.zookeeper.KeeperException;
    
    import com.zhen.zookeeper.ConnectionWatcher;
    
    /**
     * @author FengZhen
     * @date 2018年10月13日
     * 删除组
     * 
     */
    public class DeleteGroup extends ConnectionWatcher{
    
    	public void delete(String groupName) {
    		String path = "/" + groupName;
    		try {
    			List<String> children = zk.getChildren(path, false);
    			for (String child : children) {
    				zk.delete(path + "/" + child, -1);
    			}
    			/**
    			 * delete方法有两个参数
    			 * path:节点路径
    			 * -1:版本号
    			 * 如果所提供的版本号与znode的版本号一致,ZK会删除这个znode。
    			 * 这是一种乐观的加锁机制,使客户端能够检测出对znode的修改冲突。
    			 * 通过将版本号设置为-1,可以绕过这个版本检测机制,不管znode的版本号是什么而直接将其删除。
    			 * ZK不支持递归删除,因此在删除父节点之前必须先删除子节点
    			 */
    			zk.delete(path, -1);
    		} catch (KeeperException e) {
    			System.out.printf("Group %s does not exist
    ", groupName);
    			System.exit(1);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String[] args) throws IOException, InterruptedException {
    		String hosts = "localhost:2181";
    		String groupName = "zoo";
    		DeleteGroup deleteGroup = new DeleteGroup();
    		deleteGroup.connect(hosts);
    		deleteGroup.delete(groupName);
    		deleteGroup.close();
    	}
    	
    }
    

      

  • 相关阅读:
    Django学习之文件下载
    Django学习之文件上传
    Django基础十一之认证系统
    Django基础之jQuery操作
    Django基础之django分页
    CVE-2019-17671:wrodpress 未授权访问漏洞-复现
    CVE-2020-1938:Apache-Tomcat-Ajp漏洞-复现
    Xray安装与使用
    内网渗透扫描器详解
    数据库注入详解
  • 原文地址:https://www.cnblogs.com/EnzoDin/p/9783382.html
Copyright © 2020-2023  润新知