原生api的不足
- 连接的创建是异步的, 需要开发人员自行编码实现
- 连接没有自动的超时重试机制
- zk本身不提供序列化机制,需要开发人员自行指定,从而实现序列化反序列化机制
- watcher 注册一次只会生效一次, 需要不断注册
- Watcher的使用方式不符合java本身的术语,如果采用监听器方式更容易理解。
- 不支持递归创建树形节点
curator 有点
- 解决session会话超时重连
- Watcher反复注注册
- 简化开发api
- 遵循Fluent风格Api规范
- NodeExistsException异常处理
- 大招:共享锁服务, master 选举, 分布式计数问题
- 还有…
- http://curator.apache.org/
创建会话
使用CuratorFrameworkFactory工厂的两个静态方法创建客户端
- static CuratorFramework newClient(String connectString, int sessionTimeoutMs, int connectionTimeoutMs,RetryPolicy retryPolicy)
static CuratorFramework newClient(String connectString, RetryPolicy retryPolicy)
start() 启动方法
- close() 关闭方法
参数名说明
- connectString: 逗号分开的ip:port 对
- retryPolicy: 重试策略, 默认4种: Exponential BackoffRetry, RetryNTimes , RetryOneTime, RetryUntilElapsed
- sessionTimeoutMs: 会话超时时间,单位ms, 默认 600000ms
- connectionTimeoutMs: 连接超时, 单位ms, 默认 1500ms
重试策略
实现 RetryPolic 的自定义重试策略
boolean allowRetry(int retryCount, long elapsedTimeMs, RetrySleeper sleeper)
参数说明:
retryCount: 已经重试的次数,如果第一次重试,此值 0
elapsedTimeMs: 重试花费的时间,单位为毫秒
sleeper: 类似于Thread.sleep,用于sleep指定时间
返回值: true: 继续重试, false: 停止重试
默认重试策略 ExponentialBackoffRetry
ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries)
ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries, int maxSleepMs)
当前该sleep的时间: baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)))
参数说明:
baseSleepTimeMs: 初始sleep时间
maxRetries: 最大重试次数
maxSleepMs: 最大重试时间
返回值: true: 继续重试, false: 停止重试
默认重试策略 RetryNTimes
- RetryNTimes(int n, int sleepMsBetweenRetries)
- 当前该sleep的时间: sleepMsBetweenRetries
参数说明:
n: 最大重试次数
sleepMsBetweenRetries:重试时间间隔
默认重试策略 RetryOneTime
- RetryOneTime(int sleepMsBetweenRetry), sleepMsBetweenRetry为重试间隔的时间
- 只重试一次
默认重试策略 RetryUntilElapsed
RetryUntilElapsed(int maxElapsedTimeMs, int sleepMsBetweenRetries)
重试的时间超过最大时间后,就不再重试
参数说明:
maxElapsedTimeMs: 最大的重试时间
sleepMsBetweenRetries:每次重试的间隔时间
fluent api 风格
- 一种面向对象的开发方式, 目的是提高代码的可读性
- 实现方式: 通过方法的级联或者方法链的方式实现.
举例:
CuratorFramework cf=CuratorFrameworkFactory.builder()
.connectString(“localhost:2181,localhost:2182”)
.sessionTimeout(10000).namespace(“base”).build();
创建节点
- 构建操作包类builder: CreateBuilder create() –CuratorFramework
- CreateBuilder
- creatingParentsIfNeeded() // 递归创建父目录
- withMode(CreateMode mode) //设置节点属性 比如: CreateMode.PERSISTENT, 如果是递归创建, 创建模式为临时节点, 则只有叶节点是临时节点. 非页节点都为持久节点.
- withAcl(List aclList) //设置Acl
- forPath(String path) //指定路径
删除节点
- 构建操作包类builder: DeleteBuilder delete() –CuratorFramework
- DeleteBuilder()
- withVersion(int version) // 特定版本号
- guaranteed() 确保节点被删除
- forPath(String path) //指定路径
- deletingChildrenIfNeeded() // 递归删除所有子节点
异步操作
- inBackground()
- inBackground(Object context)
- inBackground(BackgroundCallback callback)
- inBackground(BackgroundCallback callback, Object context)
- inBackground(BackgroundCallback callback, Executor executor)
- inBackground(BackgroundCallback callback, Object context, Executor executor)
- BackgroundCallback
- public void processResult(CuratorFramework client, CuratorEvent event) throws Exception;
- 从参数看跟zk的原生异��api相同,多了一个线程池,用于执行回调
读数据
- 构建操作包类builder: GetDataBuilder getData() –CuratorFramework
- GetDataBuilder
- storingStatIn(org.apache.zookeeper.data.Stat stat) // 获取服务端状态数据到stat对象
- Byte[] forPath��String path //指定路径
更新数据
- 构建操作包类builder: SetDataBuilder setData() –CuratorFramework
- SetDataBuilder()
- withVersion(int version) // 特定版本号, -1 档期版本号
- forPath(String path,byte[] data) //节点路��
- forPath(String path) //指定路径
- deletingChildrenIfNeeded() // 递归删除所有子节点
读取子节点
- 构建操作包类builder: GetChildrenBuilder getChildren() –CuratorFramework
- GetChildrenBuilder()
- storingStatIn(org.apache.zookeeper.data.Stat stat) //获取服务端状态数据到stat对象
- List forPath(String path)
- usingWatcher(org.apache.zookeeper.Watcher watcher) // 设置watcher, 类似于zk自身的api, 只能使用一次
- usingWatcher(CuratorWatcher watcher) // 设置watcher, 类似于zk自身的api, 只能使用一次
设置watcher NodeCache
- 监听数据节点内容的变更
- 监听节点的创建,即如果指定的节点不存在,则节点创建后,会触发这个监听
- 构造函数
- NodeCache(CuratorFramework client, String path)
- NodeCache(CuratorFramework client, String path, boolean dataIsCompressed)
- client: 客户端
- path: 监听路径
- dataIsCompressed: 是否进行数据压缩
- 回调接口
- public interface NodeCacheListener
- void nodeChanged() // 没有参数,怎么获取事件信息以及节点数据呢
- 事件信息封装在NodeCache的CurrentData中
- public interface NodeCacheListener
设置watcher PathChildrenCache
- 监听指定节点的子节点变化
- 包括新增子节点, 子节点数据变更和字节点删除
- 构造函数
- PathChildrenCache(CuratorFramework client, String path, boolean cacheData)
- PathChildrenCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed,CloseableExecutorService executorService)
- PathChildrenCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed,ExecutorService executorService)
- PathChildrenCache(CuratorFramework client, String path, boolean cacheData, boolean dataIsCompressed,ThreadFactory threadFactory)
- PathChildrenCache(CuratorFramework client, String path, boolean cacheData, ThreadFactory threadFactory)
- 参数说明
- client : 客户端
- path: 路径
- cacheData: 是否缓存数据
- executorService/ threadFactory : 构造专门的线程池来处理事件
- 回调接口
- interface PathChildrenCacheListener
- void childEvent(CuratorFramework client, PathChildrenCacheEvent event)
- 监听接口
- 时间类型包括: 新增子节点(Child_add), 子节点变更(child_updated), 子节点删除(child_removed)
- PathChildrenCache.StartMode
- BUILD_INITIAL_CACHE: 同步初始化客户端的cache,及cache创建后, 就从服务器端拉取对应的数据
- NORMAL: 异步初始化cache
- POST_INITIALIZED_EVENT: 异步初始化, 初始化完成触发事件PathChildrenCacheEvent.Type.INITIALIZED
设置watcher TreeCache
既可以监控节点的状态也可以监控子节点的状态, 类似于上面两种的组合. 监控整个树中的状态.
- 使用之前需要调用start 方法
不用需要调用 close 方法
构造函数
- public TreeCache(CuratorFramework client, String path)
参数说明
- client : 客户端
- path: 路径
回调接口
- interface TreeCacheListener
- public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception;
TreeCacheEvent
- NODE_ADDED, NODE_UPDATED, NODE_REMOVED
- data: ChildData