Zookeeper的监听机制api与原理

本文详细介绍了如何连接Zookeeper并注册监听,包括对getChildren和getData的监听。虽然这些监听默认只触发一次,但通过在process方法中设置参数为true,可以实现对节点变化的永久监听。当节点数据或子节点发生变化时,Zookeeper能够动态通知客户端,保持实时同步。

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<String> 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<String> children = zkCli.getChildren("/servers", true);
		ArrayList<String> serverList = new ArrayList<String>();
		
		//获取每个节点的数据
		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<String> children;	
				try {
					//监听父节点
					children = zkCli.getChildren("/servers", true);
					
					//创建集合存储服务器列表
					ArrayList<String> serverList = new ArrayList<String>();
					
					//获取每个节点的数据
					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方法中的语句.这里就证明了我的理解应该是对了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值