原生api的不足:
(1)连接的创建是异步的,需要开发人员自行编码实现等待。
(2)连接没有自动的超进重连机制。
(3)zk本身没提供序列化机制,需要开发人员自行指定,从而实现数据的序列化和反序列化。
(4)Watcher注册一次只会生效一次,需要不断的重复注册。
(5)不支持递归创建树形节点。
使用Java操作zookeeper时,一般有两种方式:zkclient和curator,相比较来说,curator的使用较为简单。
CuratorFrameworkFactory 的静态方法创建客户端
(a)static CuratorFramework newClient(String connectString , int sessionTimeoutMs, int connectionTimeoutMs, RetryPolicy retryPolicy)
(b)static CuratorFramework newClient(String connectString, RetryPolicy retryPolicy)
参数说明:
- connectString 分开的ip:port对。
- retryPolicy:重试策略
- sessionTimeoutMs:会话超时时间,默认60000ms
- connectionTimeoutMs:连接创建超时时间,单位为毫秒,默认是15000ms
实现接口RetryPolicy可以自定义重试策略:
boolean allowRetry(int retryCount, long elapsedTimeMs, RetrySleeper sleeper)
- retryCount:已经重试的次数,如果第一次重试,此值为0.
- elapsedTimeMs:重试花费的时间
- sleeper:类似于Thread.sleep,用于sleep指定时间。
- 返回值:如果还会继续重试,则返回true
默认重试策略:
(1)RetryNTimes(int n, int sleepMsBetweenRetries)
- n:最大重试次数。
- sleepMsBetweenRetry:重试间隔的时间。
(2)RetryOneTime(int sleepMsBetweenRetry)
- sleepMsBetweenRetry:重试间隔的时间
(3)RetryUntilElapsed(int maxElapsedTimeMs, int sleepMsBetweenRetries)
重试的时间超过最大时间后,就不再重试。
- maxElapsedTimeMs:最大重试时间。
- sleepMsBetweenRetriees:每次重试的间隔时间。
(4)ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries, int maxSleepMs)
- baseSleepTimeMs:初始sleep时间。
- maxRetries:最大重试次数。
- maxSleepMs:最大重试时间。
当前应该sleep的时间:baseSleepTimeMs*Math.max(1,random.nextInt(1<<retryCount+1)),随着重试次数,增加重试时间间隔,指数增加。
Fluent风格的API
一种面向对象的开发方式,目的是提高代码的可读性。
例子:
zkclient = CuratorFramework.builder().connectString(connectString).sessionTimeoutMs(5000).retryPolicy(retryPolicy)。
创建节点
CreateBuilder create()
- createingParentsIfNeeded()递归创建父目录。
- withMode(CreateMode mode)设置节点属性,如果是递归创建,创建模式为临时节点,则只有叶子节点是临时节点,非叶子都为持久节点。
- withACL(List aclList)
- forPath(String path) 指定路径。
删除节点
DeleteBuilder delete()
- withVersion(int version)
- guaranteed() 确保节点被删除
- forPath(String path) 指定路径
- deletingChildrenIfNeeded 递归删除所有子节点
读取数据
GetDataBuilder getData()
- storingStatIn(org.apache.zookeeper.data.Stat stat) 把服务器端获取的状态数据存储到stat对象。
- Byte[] forPath(String path) 节点路径
设置watcher
(1)NodeCache
监听数据节点的内容变更,如果指定的节点不存在,则节点创建后,会触发这个监听。
(2)PathChildrenCache
监听指定节点的子节点变化情况。
package com.zk.dev.zkClient.day1;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs.Ids;
/**
* @see 测试curator框架例子
* @Author:xuehan
* @Date:2016年5月14日下午8:44:49
*/
public class CuratorUtils {
public String connectString = "localhost:2181";
CuratorFramework zkclient = null ;
public CuratorUtils(){
/**
* connectString连接字符串中间用分号隔开,sessionTimeoutMs session过期时间,connectionTimeoutMs连接超时时间,retryPolicyc连接重试策略
*/
//CuratorFrameworkFactory.newClient(connectString, sessionTimeoutMs, connectionTimeoutMs, retryPolicy)
// fluent风格aip
// CuratorFrameworkFactory.builder().sessionTimeoutMs(5000).connectString(connectString).namespace("/test").build();
// 重连策略,没1一秒重试一次,最大重试次数3次
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
zkclient = CuratorFrameworkFactory.builder().connectString(connectString).sessionTimeoutMs(5000).retryPolicy(retryPolicy).namespace("tests").build();
zkclient.start();
}
/**
* 递归创建节点
* @param path
* @param data
* @throws Exception
*/
public void createNode(String path, byte[] data) throws Exception{
zkclient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(Ids.OPEN_ACL_UNSAFE).forPath(path, data);
}
/**
* 递归删除节点
* @param path
* @throws Exception
*/
public void delNode(String path) throws Exception{
zkclient.delete().guaranteed().deletingChildrenIfNeeded().forPath(path);
} public void zkClose(){
zkclient.close();
}
public void delNodeCallBack(String path) throws Exception{
zkclient.delete().guaranteed().deletingChildrenIfNeeded().inBackground(new DeleteCallBack()).forPath(path);
}
public void dataChanges(String path) throws Exception{
final NodeCache dataWatch = new NodeCache(zkclient, path);
dataWatch.start(true);
dataWatch.getListenable().addListener(new NodeCacheListener(){
public void nodeChanged() throws Exception {
System.out.println("path==>" + dataWatch.getCurrentData().getPath() + "==data==>" + new String(dataWatch.getCurrentData().getData()));
}
});
zkclient.delete().guaranteed().deletingChildrenIfNeeded().inBackground(new DeleteCallBack()).forPath(path);
}
public void addChildWatcher(String path) throws Exception{
final PathChildrenCache pc = new PathChildrenCache(zkclient, path, true);
pc.start(StartMode.POST_INITIALIZED_EVENT);
System.out.println("节点个数===>" + pc.getCurrentData().size());
pc.getListenable().addListener(new PathChildrenCacheListener() {
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("事件监听到" + event.getData().getPath());
if(event.getType().equals(PathChildrenCacheEvent.Type.INITIALIZED)){
System.out.println("客户端初始化节点完成" + event.getData().getPath());
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){
System.out.println("添加节点完成" + event.getData().getPath());
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)){
System.out.println("删除节点完成" + event.getData().getPath());
}else if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
System.out.println("修改节点完成" + event.getData().getPath());
}
}
});
}
public static void main(String[] args) throws Exception{
CuratorUtils cu = new CuratorUtils();
// cu.createNode("/test/sb/aa/bb", "erhu".getBytes());
// cu.delNode("/test");
cu.zkclient.setData().forPath("/aa", "love is not".getBytes());
cu.addChildWatcher("/aa");
try{
Thread.sleep(20000000);
}catch(Exception e){};
}
}
最后欢迎大家访问我的个人网站:1024s