利用Zookeeper 临时型节点特性(当断开连接时, 创建的临时性节点自动销毁), 可实现监听集群节点动态上下线的功能. 所谓监听监听节点动态上下线是指, 当有节点新增或删除时, 监听端都会收到信息. zookeeper 实现的监听节点动态上下线特点:
- 通过向节点注册监听器, 来监听该节点子节点的创建和删除
- 当子节点有创建和删除操作时, 监听端会接收到事件, 但是却不知道具体是新增或删除哪个节点, 需要重新查询所有子节点数据, 来进行更新列表
- 使用局部监听器时,需要注意局部监听器只能监听一次事件. 当监听到事件后, 需要将监听器自身再次注册为监听器, 才能保证继续监听
- zk 监听类似于广播, 当一个节点注册了多个监听器时, 当有事件发生时, 事件会通知给所有监听器
1. 注册端开发
1.1 创建全局监听器
笔者习惯于也建议, 创建一个全局监听器类, 而不是采用内部类实现, 纵使笔者的全局事件监听器并未做任何处理. 笔者觉得这样会使代码更清晰.
public class RegisterGlobalWatcher implements Watcher {
@Override
public void process(WatchedEvent event) {
}
}
1.2 创建zk 客户端连接,并注册监听器
笔者采用静态代码块儿来初始化zk 连接, 这样能保证连zk 连接只会被创建一次. 当结合spring 使用时, 只需要使用@Component 将此类的实例注册为sprin 容器的一个组件即可.
public class ZkRegisteClient {
private static Logger logger = LoggerFactory.getLogger(ZkRegisteClient.class);
private static ZooKeeper zooKeeper;
// 使用static 方式, 在类加载时, 只执行一次
static {
// 创建zookeeper 连接时, 设置全局监听器
try {
zooKeeper = new ZooKeeper(ZkConstant.SERVER, ZkConstant.SESSION_TIMEOUT, new RegisterGlobalWatcher());
} catch (IOException e) {
throw new RuntimeException("创建连接失败");
}
//注册节点
rigeste();
}
/**
* @Description: 注册节点
* @author: zongf
* @time: 17:30:07
*/
private static void rigeste(){
try {
// 如果nodes 节点不存在, 则创建nodes 节点
if(null == zooKeeper.exists(ZkConstant.PATH_NODES, false)){
zooKeeper.create(ZkConstant.PATH_NODES, "集群节点列表".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
// 获取本机主机ip
String address = InetAddressUtil.getHostIp();
// 节点路径 TODO 根据自居需要设置在数据内容
String nodePath = ZkConstant.PATH_NODES + "/" + address + "-";
// 节点数据 TODO 根据自居需要设置在数据内容
String data = "{\"host\":\"" + address + "\", time:\"" + getDateTime() + "\"}";
// 如果节点存在则先删除
Stat stat = zooKeeper.exists(nodePath, false);
if(stat != null){
zooKeeper.delete(nodePath, stat.