zookeeper系列(六) curator三种监听器(Cache)方式

本文深入探讨了Zookeeper中三种监听机制:NodeCache用于监听单一节点变化,PathChildrenCache关注节点子节点变动,而TreeCache则全面监测节点及其子孙节点的动态。通过具体示例,演示了每种机制的实现过程及输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

 

1. NodeCache

2. PathChildrenCache

3. TreeCache


1. NodeCache

这是最简单的一种监听方式,只监听固定节点的内容变化。

public class CuratorBaseTest {
	
	/*	url : zookeeper 地址
	 * 	namespace : 起始路径
	 *  id0 : 用户名
	 *  id1 : 密码
	 * */
	public static CuratorFramework buildConnect(String url,String namespace, String id0, String id1)
	{
		 //创建权限管理器
		 ACLProvider aclProvider = new ACLProvider() {
	            private List<ACL> acl;
	            @Override public List<ACL> getDefaultAcl() {
	                if (acl == null) {
	                    ArrayList<ACL> acl = ZooDefs.Ids.CREATOR_ALL_ACL; //初始化
	                    acl.clear();
	                    acl.add(new ACL(Perms.ALL, new Id("auth", id0 + ":" + id1)));//添加
	                    this.acl = acl;
	                }
	                return acl;
	            }
	            @Override public List<ACL> getAclForPath(String path) {
	                return acl;
	            }
	        };
	        
		CuratorFramework curatorFramework = 
				CuratorFrameworkFactory.builder()  
				.aclProvider(aclProvider)
                .connectString(url)
                .authorization("digest", (id0 + ":" + id1).getBytes()) //使用用户名/密码进行连接
                .retryPolicy(new ExponentialBackoffRetry(100, 6))  //重试策略
                .build();
		curatorFramework.start();
		
        try {
            curatorFramework.blockUntilConnected(3, TimeUnit.SECONDS); //阻塞判断连接成功,超时认为失败。
            if (curatorFramework.getZookeeperClient().isConnected()) {
                return curatorFramework.usingNamespace(namespace); //返回连接,起始根目录为namespace。
            }
        } catch (InterruptedException ignored) {
            Thread.currentThread().interrupt();
        }

        // fail situation
        curatorFramework.close();
        throw new RuntimeException("failed to connect to zookeeper service : " + url);
	}
}
public class CuratorNodeCacheTest {
	
	
	public static void main(String[] args) {
		
		try {
			
			String testPath="nodeCacheTest";
			//创建连接
			CuratorFramework client= CuratorBaseTest.buildConnect("192.168.10.1:2181,192.168.10.2:2181","test","test","test");
			//如果testPath存在,删除路径
			Stat stat = client.checkExists().forPath("/"+testPath);
			if(stat != null)
			{
				client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/"+testPath);
			}
			//创建testPath
			client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/"+testPath,testPath.getBytes());
			//创建NodeCache,监控节点内容变化。
			final NodeCache nodeCache = new NodeCache(client,"/" + testPath);
			nodeCache.start();
			//创建listenner
			nodeCache.getListenable().addListener(new NodeCacheListener() {
	            @Override
	            public void nodeChanged() throws Exception {
	                System.out.println("节点内容变化:" + new String(nodeCache.getCurrentData().getData()));
	            }
	        });
			//第一次修改节点
			client.setData().forPath("/" + testPath,"1".getBytes());
			//此处如果不睡眠,两次修改时间太近,第一次修改的内容会丢失,监听器会察觉不到第一次修改。
			Thread.sleep(1000);
			//第二次修改节点
		    client.setData().forPath("/" + testPath,"2".getBytes());
		    Thread.sleep(1000);
		    //删除节点
		    client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/"+testPath);
		    Thread.sleep(1000);
		    //重新创建节点
		    client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/"+testPath,testPath.getBytes());
		    Thread.sleep(1000); 
		    //第三次更改节点
		    client.setData().forPath("/" + testPath,"3".getBytes());
		    Thread.sleep(1000); 
		    //关闭
		    nodeCache.close();
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}
		
	}
}

输出:

节点内容变化:1

节点内容变化:2

节点内容变化:nodeCacheTest

节点内容变化:3

 

2. PathChildrenCache

此种方式只监听某个节点的子节点变化,不关心孙子节点的变化。

public class CuratorPathChildrenCacheTest {
	
	public static void main(String[] args) {
		
		try {
			String testPath="pathChildrenCacheTest";
			//创建连接
			CuratorFramework client= CuratorBaseTest.buildConnect("192.168.10.1:2181,192.168.10.2:2181","test","test","test");
			//如果testPath存在,删除路径
			Stat stat = client.checkExists().forPath("/"+testPath);
			if(stat != null)
			{
				client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/"+testPath);
			}
			//创建testPath
			client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/"+testPath,testPath.getBytes());
			
			//创建PathChildrenCache
			//参数:true代表缓存数据到本地
			PathChildrenCache pathChildrenCache = new PathChildrenCache(client,"/" + testPath,true);
			//BUILD_INITIAL_CACHE 代表使用同步的方式进行缓存初始化。
			pathChildrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
	        pathChildrenCache.getListenable().addListener((cf, event) -> {
	            PathChildrenCacheEvent.Type eventType = event.getType();
	            switch (eventType) {
	                case CONNECTION_RECONNECTED:
	                	pathChildrenCache.rebuild();
	                    break;
	                case CONNECTION_SUSPENDED:
	                    break;
	                case CONNECTION_LOST:
	                    System.out.println("Connection lost");
	                    break;
	                case CHILD_ADDED:
	                	 System.out.println("Child added");
	                    break;
	                case CHILD_UPDATED:
	                	System.out.println("Child updated");
	                    break;
	                case CHILD_REMOVED:
	                	System.out.println("Child removed");
	                    break;
	                default:
	            }
	        });
	        
	        //创建子节点1
	        client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/"+testPath+"/1",testPath.getBytes());
	        Thread.sleep(1000);
	        //创建子节点1
	        client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/"+testPath+"/2",testPath.getBytes());
	        Thread.sleep(1000);
	        //删除子节点1
	        client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/"+testPath+"/1");
	        Thread.sleep(1000);
	        //删除子节点2
	        client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/"+testPath+"/2");
	        Thread.sleep(1000);
	        
	        pathChildrenCache.close();
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}
		
		
	}
}

输出:

Child added

Child added

Child removed

Child removed

 

3. TreeCache

此种方式已树形的方式监听某个节点下所有子孙节点的变化,例如子节点的子节点。

public class CuratorTreeCacheTest {

	public static void main(String[] args) {

		try {
			String testPath = "treeCacheTest";
			// 创建连接
			CuratorFramework client = CuratorBaseTest.buildConnect("192.168.10.1:2181,192.168.10.2:2181", "test", "test",
					"test");
			// 如果testPath存在,删除路径
			Stat stat = client.checkExists().forPath("/" + testPath);
			if (stat != null) {
				client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/" + testPath);
			}
			// 创建testPath
			client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/" + testPath,
					testPath.getBytes());

			final TreeCache cached = new TreeCache(client, "/" + testPath);
			cached.getListenable().addListener((cli, event) -> {
				TreeCacheEvent.Type eventType = event.getType();
				switch (eventType) {
				case CONNECTION_RECONNECTED:
					break;
				case CONNECTION_SUSPENDED:
					break;
				case CONNECTION_LOST:
					System.out.println("Connection lost");
					break;
				case NODE_ADDED:
					System.out.println("Node added:" + event.getData().getPath());
					break;
				case NODE_UPDATED:
					System.out.println("Node updated");
					break;
				case NODE_REMOVED:
					System.out.println("Node removed:" + event.getData().getPath());
					break;
				default:
				}
			});
			
			cached.start();

			// 创建子节点1
			client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT)
					.forPath("/" + testPath + "/1", testPath.getBytes());
			Thread.sleep(1000);
			// 创建子节点1/11
			client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT)
					.forPath("/" + testPath + "/1/11", testPath.getBytes());
			Thread.sleep(1000);
			// 删除子节点1/11
			client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/" + testPath + "/1/11");
			Thread.sleep(1000);
			// 删除子节点1
			client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/" + testPath + "/1");
			Thread.sleep(1000);

			cached.close();
		} catch (Exception e) {
			// TODO: handle exception
		}

	}

}

输出:

Node added:/treeCacheTest

Node added:/treeCacheTest/1

Node added:/treeCacheTest/1/11

Node removed:/treeCacheTest/1/11

Node removed:/treeCacheTest/1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值