Zookeeper的监听机制api与原理

1.连接Zookeeper,注册监听

ZooKeeper zkCli = new ZooKeeper("192.168.50.183:2181,192.168.50.184:2181,192.168.50.185:2181", 3000, new Watcher() {
				//监听回调
				@Override
				public void process(WatchedEvent event) {
					System.out.println("正在监听中.....");
				}
			});

2.注册监听getChilren

通过zkCli.getchildren("/",new watch()){}来注册监听,监听的是整个根节点,但是这个监听只能监听一次。
线程休眠是为了让监听等待事件发生,不然会随着程序直接运行完。

public class WatchDemo1 {
	
	static List children = null;
	public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
		

		ZooKeeper zkCli = new ZooKeeper("192.168.50.183:2181,192.168.50.184:2181,192.168.50.185:2181", 3000, new Watcher() {
				
				//监听回调
				@Override
				public void process(WatchedEvent event) {
					System.out.println("正在监听中.....");
				}
			});
		
			//监听目录
			children = zkCli.getChildren("/", new Watcher() {
			
			@Override
			public void process(WatchedEvent event) {
				
				System.out.println("监听路径为:" + event.getPath());
				System.out.println("监听的类型为:" + event.getType());
				System.out.println("数据被2货修改了!!!");
				
				for(String c:children) {
					System.out.println(c);
				}
			}
		});
			
			Thread.sleep(Long.MAX_VALUE);
		
	}
	
		
}

可以通过修改zk客户端的/节点下的子节点,getchilren会返回列表(/下的子节点信息)

3.注册监听getData

getData监听的为一个节点
同样只监听一次,返回的是该节点的内容

public class WatchDemo {
	public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
		ZooKeeper zkCli = new ZooKeeper("192.168.50.183:2181,192.168.50.184:2181,192.168.50.185:2181", 3000, new Watcher() {
			
			//监听回调
			@Override
			public void process(WatchedEvent event) {
				
			}
		});
		
		byte[] data = zkCli.getData("/hunter", new Watcher() {
			//监听的具体内容
			@Override
			public void process(WatchedEvent event) {
				System.out.println("监听路径为:" + event.getPath());
				System.out.println("监听的类型为:" + event.getType());
				System.out.println("数据被2货修改了!!!");
			}
		}, null);
		
		System.out.println(new String(data));
		
		Thread.sleep(Long.MAX_VALUE);
	}
}

4.永久监听

public class ZkClient {
	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
		//1.获取连接
		ZkClient zkClient = new ZkClient();
		zkClient.getConnect();
		
		//2.监听服务的节点信息
		zkClient.getServers();;
		
		//3.业务逻辑(一直监听)
		zkClient.getWatch();
	}
	
	//3.业务逻辑
	public void getWatch() throws InterruptedException {
		Thread.sleep(Long.MAX_VALUE);
	}
	
	//2.监听服务的节点信息
	public void getServers() throws KeeperException, InterruptedException {
		List children = zkCli.getChildren("/servers", true);
		ArrayList serverList = new ArrayList();
		
		//获取每个节点的数据
		for(String c:children) {
			byte[] data = zkCli.getData("/servers/" + c, true, null);
			serverList.add(new String(data));
		}
		
		//打印服务器列表
		System.out.println(serverList);
		
	}
	
	private String connectString = "192.168.232.132:2181,192.168.232.133:2181,192.168.232.134:2181";
	private int sessionTimeout = 3000;
	ZooKeeper zkCli;
	
	//1.连接集群
	public void getConnect() throws IOException {
		zkCli = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
			
			@Override
			public void process(WatchedEvent event) {
				List children;	
				try {
					//监听父节点
					children = zkCli.getChildren("/servers", true);
					
					//创建集合存储服务器列表
					ArrayList serverList = new ArrayList();
					
					//获取每个节点的数据
					for(String c:children) {
						byte[] data = zkCli.getData("/servers/" + c, true, null);
						serverList.add(new String(data));
					}
					
					//打印服务器列表
					System.out.println(serverList);
					
				} catch (KeeperException e) {
					
					e.printStackTrace();
				} catch (InterruptedException e) {
					
					e.printStackTrace();
				}
			}
		});
	}
	
}

服务端上下线机器,客户端都能动态感知,这里是先通过getchilren获得根节点下的子节点信息列表,然后通过getData来获得每个子节点的内容,并传给ArrayList,最后通过输出ArrayList来获得当前在线的机器

5.总结

1.从1-3的代码可以看出,zookeeper注册的监听是一次的,如果你还需要监听第二次,那么就要重新注册。
那我们永久监听是怎么做到的呢?
2.可以看到在我们连接zookeeper的时候,注册了监听,然后在process方法中,我们的getChildren,getData的第二个参数为true,这里是使用默认的监听,我的理解是会回调到我们连接zookeeper的时候注册监听的process方法,那因为我们的getChildren,getData是放在这个方法里的,每次发生一个事件,然后就一直重复这样的行为,达到永久监听的效果。
3.这里我们可以测试下,getChildren,getData不放在process当中,并且参数为true,那我的测试结果为,监听了一次,监听完了后,又返回连接zk时的process方法中的语句.这里就证明了我的理解应该是对了。

你可能感兴趣的:(zookeeper)