Zookeeper 可以监听节点数据变化或子节点数量变化. 当监听的事件发生后, 会通知监听器对事件做相应的处理.
1. Zookeeper监听
1.1 监听器类型
从监听器范围来区分, Zookeeper 监听器分为两种, 一种是全局监听器,一种是局部监听器.
- 全局监听器: 创建Zookeeper 连接时指定, 全局唯一. 一旦注册不能删除, 默认无限监听事件.
- 局部监听器: 对节点进行操作时, 指定具体场景的监听器. 默认一次注册监听, 只能处理一次事件触发.
1.2 事件类型
Zookeeper 监听的事件类型有四种:
- EventType.NodeCreated: 节点创建事件
- EventType.NodeDeleted: 节点删除事件
- EventType.NodeDataChanged: 节点数据内容变更
- EventType.NodeChildrenChanged: 子节点数量发生变化, 新增或删除子节点. 子节点内容发生变化, 不会触发.
2. 使用全局监听器监听
- 一条Zookeeper 连接只有一个全局监听器, 在创建Zookeeper对象时指定
- 全局监听器中监听的事件, 只能注册, 不能删除. 除非断开连接, 重新连接. 因此要慎用
- 全局监听器中监听的事件, 会循环监听. 并非触发一次就终止了.
- 全局监听器中需要根据节点路径和事件类型综合判断来做相应的业务逻辑.
2.1 全局监听器API
- 使用全局监听器的API 都会传一个boolean 类型为true的参数, 声明此操作需要监听, 会在全局监听器中注册一条监听信息, 但不能删除.
- 当监听的事件发生后, 会触发全局监听器进行处理. 因此需要在全局监听器中根据节点路径和事件类型做判断.
public byte[] getData(final String path, Boolean watcher, Stat stat);
public List<String> getChildren(final String path, Boolean watcher);
public Stat exists(final String path, Boolean watcher);
....
2.2 测试用例
public class TestWatch {
// zookeeper 地址, 多个地址以逗号割开
private static String zkServer = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183";
// 会话超时时间
private static int sessionTimeout = 3000;
// zookeeper 客户端连接
private static ZooKeeper zooKeeper;
@BeforeClass
public static void init() throws Exception{
// 创建zookeeper 连接时, 设置全局监听器
zooKeeper = new ZooKeeper(zkServer, sessionTimeout, watchedEvent ->{
try {
// 获取发生事件的节点路径
String path = watchedEvent.getPath();
// 根据节点路径和事件类型做不同的业务的处理
if ("/".equals(path) && Watcher.Event.