02.ZooKeeper的Java客户端使用
1.ZooKeeper常用客户端比较
- zookeeper自带的客户端是官方提供的,比较底层、使用起来写代码麻烦、不够直接。
- Apache Curator是Apache的开源项目,封装了zookeeper自带的客户端,使用相对简便,易于使用。
- zkclient是另一个开源的ZooKeeper客户端,其地址:https://github.com/adyliu/zkclient生产环境不推荐使用。
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.github.adyliu</groupId>
<artifactId>zkclient</artifactId>
<version>2.1.1</version>
</dependency>
- 初始化连接的问题: 在client与server之间握手建立连接的过程中,如果握手失败,执行所有的同步方法(比如create,getData等)将抛出异常
- 自动恢复(failover)的问题: 当client与一台server的连接丢失,并试图去连接另外一台server时, client将回到初始连接模式
- session过期的问题: 在极端情况下,出现ZooKeeper session过期,客户端需要自己去监听该状态并重新创建ZooKeeper实例
- 对可恢复异常的处理:当在server端创建一个有序ZNode,而在将节点名返回给客户端时崩溃,此时client端抛出可恢复的异常,用户需要自己捕获这些异常并进行重试
- 使用场景的问题:Zookeeper提供了一些标准的使用场景支持,但是ZooKeeper对这些功能的使用说明文档很少,而且很容易用错.在一些极端场景下如何处理,zk并没有给出详细的文档说明.比如共享锁服务,当服务器端创建临时顺序节点成功,但是在客户端接收到节点名之前挂掉了,如果不能很好的处理这种情况,将导致死锁
- 内部采用SLF4J 来输出日志
- 采用驱动器(driver)机制, 允许扩展和定制日志和跟踪处理
- 提供了一个TracerDriver接口, 通过实现addTrace()和addCount()接口来集成用户自己的跟踪框架
- 文档几乎没有
- 异常处理弱爆了(简单的抛出RuntimeException)
- 重试处理太难用了
- 没有提供各种使用场景的实现
- 只是一个底层实现
- 要用需要自己写大量的代码
- 很容易误用
- 需要自己处理连接丢失, 重试等
2.ZooKeeper原生客户端基本使用


public static void main(String[] args) throws IOException, KeeperException, InterruptedException
{
// 创建一个与服务器的连接 需要(服务端的 ip+端口号)(session过期时间)(Watcher监听注册)
ZooKeeper zk = new ZooKeeper("192.168.110.100:2181", 3000, new Watcher()
{
// 监控所有被触发的事件
public void process(WatchedEvent event)
{
System.out.println(event.toString());
}
});
System.out.println("OK!");
// 创建一个目录节点
/**
* CreateMode:
* PERSISTENT (持续的,相对于EPHEMERAL,不会随着client的断开而消失)
* PERSISTENT_SEQUENTIAL(持久的且带顺序的)
* EPHEMERAL (短暂的,生命周期依赖于client session)
* EPHEMERAL_SEQUENTIAL (短暂的,带顺序的)
*/
zk.create("/path01", "data01".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// 创建一个子目录节点
zk.create("/path01/path01", "data01/data01".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(new String(zk.getData("/path01", false, null)));
// 取出子目录节点列表
System.out.println(zk.getChildren("/path01", true));
// 创建另外一个子目录节点
zk.create("/path01/path02", "data01/data02".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(zk.getChildren("/path01", true));
// 修改子目录节点数据
zk.setData("/path01/path01", "data01/data01-01".getBytes(), -1);
byte[] datas = zk.getData("/path01/path01", true, null);
String str = new String(datas, "utf-8");
System.out.println(str);
// 删除整个子目录 -1代表version版本号,-1是删除所有版本
zk.delete("/path01/path01", -1);
zk.delete("/path01/path02", -1);
zk.delete("/path01", -1);
System.out.println(str);
Thread.sleep(15000);
zk.close();
System.out.println("OK");
}
3.Apache Curator基本使用
public static void main(String[] args) throws Exception
{
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", new RetryNTimes(10, 5000));
client.start();// 连接
// 获取子节点,顺便监控子节点
List<String> children = client.getChildren().usingWatcher(new CuratorWatcher()
{
@Override
public void process(WatchedEvent event) throws Exception
{
System.out.println("监控: " + event);
}
}).forPath("/");
System.out.println(children);
// 创建节点
String result = client.create().withMode(CreateMode.PERSISTENT).withACL(Ids.OPEN_ACL_UNSAFE).forPath("/test", "Data".getBytes());
System.out.println(result);
// 设置节点数据
client.setData().forPath("/test", "111".getBytes());
client.setData().forPath("/test", "222".getBytes());
// 删除节点
System.out.println(client.checkExists().forPath("/test"));
client.delete().withVersion(-1).forPath("/test");
System.out.println(client.checkExists().forPath("/test"));
client.close();
System.out.println("OK!");
}
- create() 开始创建操作, 可以调用额外的方法(比如方式mode 或者后台执行background) 并在最后调用forPath()指定要操作的ZNode
- delete() 开始删除操作. 可以调用额外的方法(版本或者后台处理version or background)并在最后调用forPath()指定要操作的ZNode
- checkExists() 开始检查ZNode是否存在的操作. 可以调用额外的方法(监控或者后台处理)并在最后调用forPath()指定要操作的ZNode
- getData() 开始获得ZNode节点数据的操作. 可以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的ZNode
- setData() 开始设置ZNode节点数据的操作. 可以调用额外的方法(版本或者后台处理) 并在最后调用forPath()指定要操作的ZNode
- getChildren() 开始获得ZNode的子节点列表。 以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的ZNode
- inTransaction() 开始是原子ZooKeeper事务. 可以复合create, setData, check, and/or delete 等操作然后调用commit()作为一个原子操作提交
client.getCuratorListenable().addListener(new CuratorListener()
{
@Override
public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception
{
System.out.println("事件: " + event);
}
});
client.getConnectionStateListenable().addListener(new ConnectionStateListener()
{
@Override
public void stateChanged(CuratorFramework client, ConnectionState newState)
{
System.out.println("连接状态事件: " + newState);
}
});
client.getUnhandledErrorListenable().addListener(new UnhandledErrorListener()
{
@Override
public void unhandledError(String message, Throwable e)
{
System.out.println("错误事件:" + message);
}
});
- CuratorListenable:当使用后台线程操作时,后台线程执行完成就会触发,例如:client.getData().inBackground().forPath("/test");后台获取节点数据,获取完成之后触发。
- ConnectionStateListenable:当连接状态变化时触发。
- UnhandledErrorListenable:当后台操作发生异常时触发。
事件类型 事件返回数据
CREATE getResultCode() and getPath()
DELETE getResultCode() and getPath()
EXISTS getResultCode(), getPath() and getStat()
GET_DATA getResultCode(), getPath(), getStat() and getData()
SET_DATA getResultCode(), getPath() and getStat()
CHILDREN getResultCode(), getPath(), getStat(), getChildren()
SYNC getResultCode(), getStat()
GET_ACL getResultCode(), getACLList()
SET_ACL getResultCode()
TRANSACTION getResultCode(), getOpResults()
WATCHED getWatchedEvent()
GET_CONFIG getResultCode(), getData()
RECONFIG getResultCode(), getData()
CuratorFramework client = CuratorFrameworkFactory.builder().namespace("MyApp") ... build();
CuratorTempFramework client = CuratorFrameworkFactory.builder()
.connectString("127.0.0.1:2181")// 连接串
.retryPolicy(new RetryNTimes(10, 5000))// 重试策略
.connectionTimeoutMs(100) // 连接超时
.sessionTimeoutMs(100) // 会话超时
.buildTemp(100, TimeUnit.MINUTES); // 临时客户端并设置连接时间
public void close();
public CuratorTransaction inTransaction() throws Exception;
public TempGetDataBuilder getData() throws Exception;
- ExponentialBackoffRetry:重试一定次数,每次重试sleep更多的时间
- RetryNTimes:重试N次
- RetryOneTime:重试一次
- RetryUntilElapsed:重试一定的时间
-------------------------------------------------------------------------------------------------------------------------------
02.ZooKeeper的Java客户端使用的更多相关文章
- Zookeeper的java客户端API使用方法(五)
前面几篇博文,我们简单的介绍了一下zookeeper,如何安装zookeeper集群,以及如何使用命令行等.这篇博文我们重点来看下Zookeeper的java客户端API使用方式. 创建会话 客户端可 ...
- ZooKeeper学习总结(2)——ZooKeeper开源Java客户端ZkClient使用
zkclient是zookeeper的Java客户端.它让Zookeeper API 使用起来更简单:它非常方便订阅各种事件并自动重新绑定事件(会话建立.节点修改.节点删除.子节点变更等):它提供了s ...
- zookeeper的Java客户端API
zookeeper作为一个分布式服务框架,主要用来解决分布式数据一致性问题,对多种语言提供了API.这里主要记录下JAVA客户端API的使用. 1.创建会话 客户端可以通过创建一个ZooKeeper实 ...
- Zookeeper 的 java 客户端都有哪些?
java 客户端:zk 自带的 zkclient 及 Apache 开源的 Curator.
- [转载] ZooKeeper的Java客户端API
转载自 http://www.cnblogs.com/ggjucheng/p/3370359.html http://zookeeper.apache.org/doc/trunk/javaExampl ...
- 六:ZooKeeper的java客户端api的使用
一:客户端链接测试 package com.yeepay.sxf.createConnection; import java.io.IOException; import org.apache.zoo ...
- ZooKeeper:Java客户端网络处理
了解ZooKeeper客户端的实现,对于使用ZooKeeper的客户端非常重要. 通过对客户端源码的阅读,了解了如下信息: 创建ZooKeeper对象时,应会创建一个ClientCnxn(代表了客户端 ...
- 12. ZooKeeper之Java客户端API使用—创建会话。
转自:https://blog.csdn.net/en_joker/article/details/78686649 客户端可以通过创建一个ZooKeeper(org.apache.zookeeper ...
- 13.Zookeeper的java客户端API使用方法
转自:https://blog.csdn.net/jiuqiyuliang/article/details/56012027
随机推荐
- Redis的5个常见应用场景
前言 Redis 是一个强大的内存型存储,具有丰富的数据结构,使其可以应用于很多方面,包括作为数据库.缓存.消息队列等等. 如果你的印象中Redis只是一个 key-value 存储,那就错过了Red ...
- unity, 导出对象到另一个项目
----更新(2015-6-26): 今天又试了一下,有时候prefabs不用导出直接拷贝过去也能用,但有时候不行.还不太清楚原因. ----旧帖: 一,正确做法: 一个对象包括资源和Hierarch ...
- Hadoop-2.2.0中文文档—— Shell命令
FS Shell 调用文件系统(FS)Shell命令应使用 bin/hadoop fs <args>的形式. 全部的的FS shell命令使用URI路径作为參数.URI格式是scheme: ...
- 479. Second Max of Array【easy】
Find the second max number in a given array. Notice You can assume the array contains at least two n ...
- nyoj746 整数划分(四)
整数划分(四) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近遇到 ...
- LINK : fatal error LNK1104
今天本来想试试opencv的,于是就在自己的机子上部署一下试试,结果一直遇到这个错误:LINK : fatal error LNK1104 环境:win7 64位 vs2012 opencv 2.4. ...
- oracle 显示格式化
sqlplus中:set wrap off; set pagesize 1000; set linesize 1000; col id format A20; //该字段最长显示20个字符 col n ...
- exchange邮箱系统增加验证码机制
首先背景是exchange的邮箱系统没有后台源代码.因为这个原因,生成验证码的机制放在aspx的runat="sever"后台代码里面. 首先需要找到iis中logon.aspx文 ...
- JackSon解析json字符串
JackSon解析json字符串 原文:http://blog.csdn.net/java_huashan/article/details/9353903 概述 jackson解析json例子 准备工 ...
- 扩展KMP - HDU 4333 Revolving Digits
Revolving Digits Problem's Link Mean: 给你一个字符串,你可以将该字符串的任意长度后缀截取下来然后接到最前面,让你统计所有新串中有多少种字典序小于.等于.大于原串. ...