zookeeper-api基本使用
org.apache.zookeeper.Zookeeper是客户端入口主类,负责建立与server的会话。它提供了以下 所示几类主要方法。
demo增删改查
我们先修改一下本地的hosts文件
并且测试一下:
现在我们来看看zookeeper的java客户端api:
我们先来初始化一下zookeeper。
public class SimpleZkClient {
private static final String connectString = "mini1:2181,mini2:2181,mini3:2181";
private static final int sessionTimeout = 2000;
ZooKeeper zkClient = null;
@Before
public void init() throws Exception {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
// 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)
System.out.println(event.getType() + "---" + event.getPath());
}
});
}
}
我们new一个zookeeper对象,里面的参数connectString是集群的zookeeper的ip和端口,sessionTimeout 是连接超时的时间,Watcher是我们的监听器。
创建节点
然后我们来看看zookeeper的创建节点的操作:
// 创建数据节点到zk中
@Test
public void testCreate() throws KeeperException, InterruptedException {
// 参数1:要创建的节点的路径 参数2:节点大数据 参数3:节点的权限 参数4:节点的类型
String nodeCreated = zkClient.create("/eclipse", "hellozk".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
//上传的数据可以是任何类型,但都要转成byte[]
}
然后我们可以看到我们根节点下面就有eclipse这个子节点了。
判断路径节点是否存在
然后我们还可以判断路径节点是否存在:
//判断znode是否存在
@Test
public void testExist() throws Exception{
Stat stat = zkClient.exists("/eclipse", false);
System.out.println(stat==null?"not exist":"exist");
}
获取节点下面的所有子节点
获取节点下面的所有子节点的操作:
// 获取子节点
@Test
public void getChildren() throws Exception {
List<String> children = zkClient.getChildren("/", true);//true表示使用初始化zookeeper时候设置的那个Watcher
for (String child : children) {
System.out.println(child);
}
Thread.sleep(Long.MAX_VALUE);
}
我们上面使用Thread.sleep(Long.MAX_VALUE)
是为了使程序不退出,便于观察到监听器的触发。
然后我们在zookeeper命令行客户端中创建一个新的节点,查看一下是否会触发事件。
然后我们可以看到触发了监听器:
我们再创建一个子节点,可以发现并不会再次触发监听器,监听器只触发一次。
我们可以在监听器触发完毕之后再注册一个监听器。
@Before
public void init() throws Exception {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
// 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)
System.out.println(event.getType() + "---" + event.getPath());
try {
//重新注册监听
zkClient.getChildren("/", true);
} catch (Exception e) {
}
}
});
}
然后我们现在再来试一次。
我们可以发现,可以多次触发监听事件。
通过上面这中方式我们保证了能够不停的触发监听事件。
Zookeeper的监听器工作机制
现在我们来了解一下Zookeeper的监听器工作机制,zookeeper是如何触发监听事件的?
现在我们的zookeeper客户端程序里面有一个main线程,然后在里面创建了一个zkclient,在这个时候就启动了两个线程。一个线程是Connector的客户端,用于和zookeeper连接去上传数据、请求数据等;还有一个线程是Listener,可以去调用我们代码里面的process方法,它会监听在一个端口。当我们调用zkClient.getChildren("/", true);
其实就是通过Connector通信线程告诉zookeeper我们监听器的通信IP和端口以及监听的path;zookeeper就会记录这些IP、端口、path,当path下的数据发生了变化,zookeeper就知道触发事件的客户端在哪里(通过IP和端口可以找到),然后可以通过socket通信也就是通过RPC去远程调用客户端,客户端收到事件只会就会去回调process方法。
获取znode的数据
@Test
public void getData() throws Exception {
byte[] data = zkClient.getData("/eclipse", false, null);
System.out.println(new String(data));
}
删除znode
@Test
public void deleteZnode() throws Exception {
//参数2:指定要删除的版本,-1表示删除所有版本
zkClient.delete("/eclipse", -1);
}
设置znode的数据
@Test
public void setData() throws Exception {
zkClient.setData("/eclipse", "aaaaaa".getBytes(), -1);
byte[] data = zkClient.getData("/eclipse", false, null);
System.out.println(new String(data));
}