006_Curator框架一

1. 为了更好的实现Java操作ZooKeeper服务器, 后来出现了非常强大的Curator框架, 目前是Apache的顶级项目。里面提供了更多丰富的操作, 例如Session超时重连、主从选举、分布式计数器、分布式锁等等适用于各种复杂的ZooKeeper场景的API封装。

2. Curator包含了几个包

2.1. curator-framework: 对ZooKeeper的底层API的一些封装。

2.2. curator-client: 提供一些客户端的操作, 例如重试策略等。

2.3. curator-recipes: 封装了一些高级特性, 如: Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等。

3. Curator框架中使用链式编程风格, 易读性更强, 使用工厂方法创建连接对象。可以使用CuratorFrameworkFactory工厂创建连接, 参数1: connectString连接字符串; 参数2: retryPolicy重试连接策略; 参数3: sessionTimeoutMs会话超时时间, 默认为60 000ms; 参数4: connectionTimeoutMs连接超时时间, 默认是15 000ms。

4. 创建节点例子

4.1. 新建一个名为Curator的Java项目, 拷入相关jar包

4.2. 创建节点代码

package com.fj.zkcurator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

public class Create {
	public static final String connectString = "192.168.25.133:2181,192.168.25.135:2181,192.168.25.138:2181";
	public static final int sessionTimeoutMs = 10 * 60 * 1000;
	public static final int connectionTimeoutMs = 5 * 1000;
	
	public static void main(String[] args) {
		// 1. 重试策略, 初试时间为1s, 最多可重试10次。
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
		// 2. 通过工厂创建连接
		CuratorFramework cf = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).
				connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();
		// 3. 开启连接
		cf.start();
		// 4. 创建节点
		try {
			// 4.1. creatingParentsIfNeeded()可以递归创建节点
			// 4.2. withMode(CreateMode.PERSISTENT)创建持久化节点
			String result = cf.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/root/child", "I am root first child.".getBytes());
			System.out.println("创建结果: " + result);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		// 5. 关闭连接
		cf.close();
	}
}

4.3. 运行结果

5. 异步创建节点例子

5.1. 异步创建节点

package com.fj.zkcurator;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

public class CreateInBackground {
	public static final String connectString = "192.168.25.133:2181,192.168.25.135:2181,192.168.25.138:2181";
	public static final int sessionTimeoutMs = 10 * 60 * 1000;
	public static final int connectionTimeoutMs = 5 * 1000;
	public static final CountDownLatch cdl = new CountDownLatch(1);
	
	public static void main(String[] args) {
		// 1. 重试策略, 初试时间为1s, 最多可重试10次。
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
		// 2. 通过工厂创建连接
		CuratorFramework cf = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).
				connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();
		// 3. 开启连接
		cf.start();
		// 4. 创建节点
		// 4.1. 线程池
		ExecutorService pool = Executors.newCachedThreadPool();
		try {
			// 4.2. creatingParentsIfNeeded()可以递归创建节点
			// 4.3. withMode(CreateMode.PERSISTENT)创建持久化节点
			// 4.4. inBackground异步后台创建节点
			cf.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT)
					.inBackground(new BackgroundCallback() {
						@Override
						public void processResult(CuratorFramework cf, CuratorEvent ce) throws Exception {
							// 异步执行完成, 发送信号量, 让后续阻塞程序能够继续向下执行
							cdl.countDown();
							
							System.out.println("resultCode: " + ce.getResultCode());
							System.out.println("type: " + ce.getType());
						}
					}, pool).forPath("/root/child01", "I am root first child.".getBytes());
			
			// 进行阻塞
			cdl.await();
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		
		// 5. 关闭连接
		cf.close();
	}
}

5.2. 运行结果

6. 获取子节点例子

6.1. 获取子节点

package com.fj.zkcurator;

import java.util.List;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class GetChildren {
	public static final String connectString = "192.168.25.133:2181,192.168.25.135:2181,192.168.25.138:2181";
	public static final int sessionTimeoutMs = 10 * 60 * 1000;
	public static final int connectionTimeoutMs = 5 * 1000;
	
	public static void main(String[] args) {
		// 1. 重试策略, 初试时间为1s, 最多可重试10次。
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
		// 2. 通过工厂创建连接
		CuratorFramework cf = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).
				connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();
		// 3. 开启连接
		cf.start();
		// 4. 获取某路径的子节点
		try {
			List<String> children = cf.getChildren().forPath("/root");
			for (String child : children) {
				System.out.println(child);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 5. 关闭连接
		cf.close();
	}
}

6.2. 运行结果

7. 获取和设置值例子

7.1. 获取和设置值

package com.fj.zkcurator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;

public class GetSetData {
	public static final String connectString = "192.168.25.133:2181,192.168.25.135:2181,192.168.25.138:2181";
	public static final int sessionTimeoutMs = 10 * 60 * 1000;
	public static final int connectionTimeoutMs = 5 * 1000;
	
	public static void main(String[] args) {
		// 1. 重试策略, 初试时间为1s, 最多可重试10次。
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
		// 2. 通过工厂创建连接
		CuratorFramework cf = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).
				connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();
		// 3. 开启连接
		cf.start();
		// 4. 设置和获取节点数据
		try {
			// 4.1. 设置节点数据
			byte[] data = cf.getData().forPath("/root/child01");
			System.out.println(new String(data));
			// 4.2. 设置节点数据, 返回属性信息
			Stat stat = cf.setData().forPath("/root/child01", "I am root first child. modify 006".getBytes());
			System.out.println("czxid: " + stat.getCzxid() + ", ctime: " + stat.getCtime() + ", cversion: " + stat.getCversion());
			System.out.println("mzxid: " + stat.getMzxid() + ", mtime: " + stat.getMtime() + ", pzxid: " + stat.getPzxid());
			System.out.println("version: " + stat.getVersion() + ", dataLength: " + stat.getDataLength() + ", aversion: " + stat.getAversion());
			System.out.println("numChildren: "+ stat.getNumChildren() + ", ephemeralOwner: " + stat.getEphemeralOwner());
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		// 5. 关闭连接
		cf.close();
	}
}

7.2. 运行结果

8. 检查节点是否存在和删除节点例子

8.1. 检查节点是否存在和删除节点

package com.fj.zkcurator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;

public class CheckExistsDelete {
	public static final String connectString = "192.168.25.133:2181,192.168.25.135:2181,192.168.25.138:2181";
	public static final int sessionTimeoutMs = 10 * 60 * 1000;
	public static final int connectionTimeoutMs = 5 * 1000;
	
	public static void main(String[] args) {
		// 1. 重试策略, 初试时间为1s, 最多可重试10次。
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
		// 2. 通过工厂创建连接
		CuratorFramework cf = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).
				connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();
		// 3. 开启连接
		cf.start();
		// 4. 删除节点
		try {
			// 4.1. 检查节点是否存在
			Stat stat = cf.checkExists().forPath("/root/child01");
			if(stat == null) {
				System.out.println("/root/child01不存在.");
			}
			if(stat != null) {
				System.out.println("开始删除/root/child01节点.");
				// 4.2. deletingChildrenIfNeeded()递归删除节点
				cf.delete().deletingChildrenIfNeeded().forPath("/root/child01");
				if(cf.checkExists().forPath("/root/child01") == null) {
					System.out.println("/root/child01节点删除成功.");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 5. 关闭连接
		cf.close();
	}
}

8.2. 运行结果

9. 我们使用NodeCache的方式去客户端实例中注册一个监听缓存, 然后实现对应的监听方法, 监听方式CuratorCacheListener。

10. 监听缓存例子

10.1. 监听缓存

package com.fj.zkcurator;

import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Consumer;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.CuratorCache;
import org.apache.curator.framework.recipes.cache.CuratorCacheListener;
import org.apache.curator.framework.recipes.cache.CuratorCacheListenerBuilder.ChangeListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

public class CuratorCacheCuratorCacheListener {
	public static final String connectString = "192.168.25.133:2181,192.168.25.135:2181,192.168.25.138:2181";
	public static final int sessionTimeoutMs = 10 * 60 * 1000;
	public static final int connectionTimeoutMs = 15 * 1000;
	public static final String PATH = "/curatorCache";
	public static final ThreadLocalRandom random = ThreadLocalRandom.current();

	public static void main(String[] args) {
		// 1. 重试策略, 初试时间为1s, 最多可重试10次。
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
		// 2. 通过工厂创建连接
		CuratorFramework cf = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs)
				.connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();
		// 3. 开启连接
		cf.start();
		// 4. 创建CuratorCacheListener
		CuratorCacheListener listener = CuratorCacheListener.builder().forCreates(new Consumer<ChildData>() {
			@Override
			public void accept(ChildData node) {
				System.out.println(String.format("%s created. value: [%s]", node.getPath(), new String(node.getData())));
			}
		}).forChanges(new ChangeListener() {
			@Override
			public void event(ChildData oldNode, ChildData node) {
				System.out.println(String.format("%s changed. oldValue: [%s] newValue: [%s]", node.getPath(),
						new String(oldNode.getData()), new String(node.getData())));
			}
		}).forDeletes(new Consumer<ChildData>() {
			@Override
			public void accept(ChildData oldNode) {
				System.out.println(String.format("%s deleted. oldValue: [%s]", oldNode.getPath(), new String(oldNode.getData())));
			}
		}).forInitialized(new Runnable() {
			@Override
			public void run() {
				System.out.println("\r\nCache initialized.");
			}
		}).build();
		// 5. 创建CuratorCache
		CuratorCache cache = CuratorCache.build(cf, PATH);
		// 6. 注册监听
		cache.listenable().addListener(listener);
		// 7. 启动cache
		cache.start();
		// 8. 创建、删除和设置节点
		try {
			for (int i = 0; i < 10; ++i) {
				int depth = random.nextInt(1, 3);
				String path = makeRandomPath(random, depth);
				System.out.println("\r\npath = " + path);
				
				if(nodeExist(cf, path)) {
					if(random.nextBoolean()) {
						cf.setData().forPath(path, UUID.randomUUID().toString().getBytes());
					} else {
						cf.delete().deletingChildrenIfNeeded().forPath(path);
					}
				} else {
					String result = cf.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, UUID.randomUUID().toString().getBytes());
					System.out.println("result = " + result);
				}
				
				Thread.sleep(5000);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		// 9. 关闭连接
		cf.close();
	}

	private static boolean nodeExist(CuratorFramework cf, String path) throws Exception {
		return cf.checkExists().forPath(path) != null ? true : false;
	}
	
	private static String makeRandomPath(ThreadLocalRandom random, int depth) {
		if (depth == 0) {
			return PATH;
		}
		return makeRandomPath(random, depth - 1) + "/" + random.nextInt(3);
	}
}

10.2. 运行结果

11. 重复注册例子

11.1. 监听

package com.fj.zkcurator.scene;

import java.util.function.Consumer;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.CuratorCache;
import org.apache.curator.framework.recipes.cache.CuratorCacheListener;
import org.apache.curator.framework.recipes.cache.CuratorCacheListenerBuilder.ChangeListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

public class CacheWather {
	private static final String connectString = "192.168.25.133:2181,192.168.25.135:2181,192.168.25.138:2181";
	private static final int sessionTimeoutMs = 10 * 60 * 1000;
	private static final int connectionTimeoutMs = 15 * 1000;
	private static final String PATH = "/superCuratorCache";
	private CuratorFramework cf = null;
	
	public CacheWather() {
		// 1. 重试策略, 初试时间为1s, 最多可重试10次。
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
		// 2. 通过工厂创建连接
		cf = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs)
				.connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();
		// 3. 开启连接
		cf.start();
		// 4. 创建CuratorCacheListener
		CuratorCacheListener listener = CuratorCacheListener.builder().forCreates(new Consumer<ChildData>() {
			@Override
			public void accept(ChildData node) {
				System.out.println(String.format("%s created. value: [%s]", node.getPath(), new String(node.getData())));
			}
		}).forChanges(new ChangeListener() {
			@Override
			public void event(ChildData oldNode, ChildData node) {
				System.out.println(String.format("%s changed. oldValue: [%s] newValue: [%s]", node.getPath(),
						new String(oldNode.getData()), new String(node.getData())));
			}
		}).forDeletes(new Consumer<ChildData>() {
			@Override
			public void accept(ChildData oldNode) {
				System.out.println(String.format("%s deleted. oldValue: [%s]", oldNode.getPath(), new String(oldNode.getData())));
			}
		}).forInitialized(new Runnable() {
			@Override
			public void run() {
				System.out.println("\r\nCache initialized.");
			}
		}).build();
		// 5. 创建CuratorCache
		CuratorCache cache = CuratorCache.build(cf, PATH);
		// 6. 注册监听
		cache.listenable().addListener(listener);
		// 7. 启动cache
		cache.start();
		// 8. 如果缓存节点不存在就创建
		try {
			if(cf.checkExists().forPath(PATH) == null) {
				cf.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(PATH, "init".getBytes());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void close() {
		if(cf != null) {
			cf.close();
		}
	}
}

11.2. UserApp

package com.fj.zkcurator.scene;

public class UserApp {
	public static void main(String[] args) {
		CacheWather ca = new CacheWather();
		System.out.println("UserApp启动成功...");
		try {
			Thread.sleep(5*60*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ca.close();
	}
}

11.3. PayApp

package com.fj.zkcurator.scene;

public class PayApp {
	public static void main(String[] args) {
		CacheWather ca = new CacheWather();
		System.out.println("PayApp启动成功...");
		try {
			Thread.sleep(5*60*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		ca.close();
	}
}

11.4. OperationNode

package com.fj.zkcurator.scene;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;

public class OperationNode {
	public static final String connectString = "192.168.25.133:2181,192.168.25.135:2181,192.168.25.138:2181";
	public static final int sessionTimeoutMs = 10 * 60 * 1000;
	public static final int connectionTimeoutMs = 5 * 1000;
	
	public static void main(String[] args) {
		// 1. 重试策略, 初试时间为1s, 最多可重试10次。
		RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10);
		// 2. 通过工厂创建连接
		CuratorFramework cf = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(sessionTimeoutMs).
				connectionTimeoutMs(connectionTimeoutMs).retryPolicy(retryPolicy).build();
		// 3. 开启连接
		cf.start();
		// 4. 节点操作
		try {
			String r1 = cf.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/superCuratorCache/child01", "child01.".getBytes());
			System.out.println("创建结果: " + r1);
			Thread.sleep(1000);
			String r2 = cf.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/superCuratorCache/child02", "child02.".getBytes());
			System.out.println("创建结果: " + r2);
			Thread.sleep(1000);
			cf.delete().deletingChildrenIfNeeded().forPath("/superCuratorCache/child02");
			Thread.sleep(1000);
			Stat stat = cf.setData().forPath("/superCuratorCache/child01", "modify child01 data.".getBytes());
			System.out.println("czxid: " + stat.getCzxid() + ", ctime: " + stat.getCtime() + ", cversion: " + stat.getCversion());
			System.out.println("mzxid: " + stat.getMzxid() + ", mtime: " + stat.getMtime() + ", pzxid: " + stat.getPzxid());
			System.out.println("version: " + stat.getVersion() + ", dataLength: " + stat.getDataLength() + ", aversion: " + stat.getAversion());
			System.out.println("numChildren: "+ stat.getNumChildren() + ", ephemeralOwner: " + stat.getEphemeralOwner());
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		// 5. 关闭连接
		cf.close();
	}
}

11.5. 运行UserApp

11.6. 运行PayApp

11.7. 运行OperationNode

11.8. UserApp监听到节点变化

11.9. PayApp监听到节点变化

11.10. 再次运行UserApp

11.11. 再次运行PayApp

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值