前面介绍了zk的一些基础知识,这篇文章主要介绍下如何在java环境下获取zk的配置信息;主要基于zk的监听器以及回调函数通过响应式编程的思想将核心代码糅合成一个工具类,几乎做到了拿来即用;

在分布式集群中,配置信息一般都会拎出来单独配置,这样避免了修改配置信息时候的复杂度,我们期望当有配置变更时集群中的节点能及时得到通知并作出响应;我们可以在每个节点中开启任务定时来zk获取信息,然后根据获取信息的前后是否有差异来判断信息是否变更,但是这种方法明显不及时,且每次轮询zk都会增加不必要的网络开销,特别是节点众多时给ZK增加了不必要的压力;所以我们更倾向于利用ZK的监听和回调机制来实现类似的统一消息配置,客户端只要注册一个监听器当节点信息发生变更时zk会主动触发对应事件,客户端监听对应事件作出响应即可;下面先贴出代码流程图,然后再贴出关键代码

代码执行流程:



关键代码如下:

1、测试类
package com.darling.service.zookeeper;

import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.ZooKeeper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; /**
* @description: 使用响应式编程思想实现基于ZK的分布式统一配置功能
* @author: dll
* @date: Created in 2022/11/1 12:21
* @version:
* @modified By:
*/
@Slf4j
public class ZkConfigTest { ZooKeeper zkClient; @Before
public void conn (){
zkClient = ZkUtil.getZkClient();
} @After
public void close (){
try {
zkClient.close();
} catch (InterruptedException e) {
e.printStackTrace();
}
} @Test
public void test() throws InterruptedException {
ConfigData configData = new ConfigData();
ZkConfigUtil watchAndCallBack = new ZkConfigUtil();
watchAndCallBack.setZkClient(zkClient);
watchAndCallBack.setConfigData(configData); watchAndCallBack.await();
String config = configData.getConfig(); while(true){ if(configData.getConfig().equals("")){
System.out.println("配置信息丢失 ......");
watchAndCallBack.await();
}else{
System.out.println(configData.getConfig()); }
// 此处睡眠的原因是为了便于日志打印
try {
Thread.sleep(600);
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
}
2、关键工具类
package com.darling.service.zookeeper;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat; import java.util.concurrent.CountDownLatch; /**
* @description:
* @author: dll
* @date: Created in 2022/11/1 12:40
* @version:
* @modified By:
*/
@Data
@Slf4j
public class ZkConfigUtil implements Watcher, AsyncCallback.StatCallback, AsyncCallback.DataCallback { ZooKeeper zkClient; ConfigData configData; CountDownLatch cc = new CountDownLatch(1); private final String nodePath = "/config"; /**
* 异步获取数据getData方法的回调
* @param rc 状态码
* @param path 路径
* @param ctx 上线文
* @param data 节点的数据
* @param stat 元数据信息
*/
@Override
public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
if (data != null ){
configData.setConfig(new String(data));
cc.countDown();
}
} /**
* exists方法的回调,当数据存在时会调回调函数
* @param rc 状态码
* @param path 路径
* @param ctx 上下文
* @param stat 元数据信息,可通过其是否为空判断是否有数据
*/
@Override
public void processResult(int rc, String path, Object ctx, Stat stat) {
log.info("进入exists方法的回调,stat:{}");
if (stat != null) {
log.info("进入exists方法的回调,stat 不为空");
// 表示path节点有数据了,可以通过getData获取
zkClient.getData(nodePath, this, this,"123");
}
} /**
* 节点变更的监听器
* @param event
*/
@Override
public void process(WatchedEvent event) {
switch (event.getType()) {
case None:
break;
case NodeCreated:
log.info("节点被创建,path:{}",event.getPath());
// 节点创建后获取一遍数据还有个额外的不可忽略的作用:即重新注册了watch,否则根据zk的watch只生效一次的规则,不会再次出发watch
zkClient.getData(nodePath, this, this,"123");
break;
case NodeDeleted:
log.info("节点被删除,path:{}",event.getPath());
configData.setConfig("");
cc = new CountDownLatch(1);
break;
case NodeDataChanged:
log.info("节点被修改,path:{}",event.getPath());
// 节点修改获取数据的作用同节点创建
zkClient.getData(nodePath, this, this,"123");
break;
case NodeChildrenChanged:
break;
}
} public void await() {
/**
* 直接获取配置前先判断配置存不存在
* 第一个参数path:配置存放的节点路径
* 第二个参数watch:path的监听,当path有变动时回调通知
* 第三个参数StatCallback:如果path下有数据会回调此方法,可以通过Stat是否为空判断path是否有数据
*/
zkClient.exists(nodePath, this,this ,"PPP");
try {
cc.await();
} catch (InterruptedException e) {
e.printStackTrace();
} }
}

zk系列二:zookeeper实战之分布式统一配置获取的更多相关文章

  1. zk系列三:zookeeper实战之分布式锁实现

    一.分布式锁的通用实现思路 分布式锁的概念以及常规解决方案可以参考之前的博客:聊聊分布式锁的解决方案:今天我们先分析下分布式锁的实现思路: 首先,需要保证唯一性,即某一时点只能有一个线程访问某一资源: ...

  2. kafka系列二:多节点分布式集群搭建

    上一篇分享了单节点伪分布式集群搭建方法,本篇来分享一下多节点分布式集群搭建方法.多节点分布式集群结构如下图所示: 为了方便查阅,本篇将和上一篇一样从零开始一步一步进行集群搭建. 一.安装Jdk 具体安 ...

  3. 分布式统一配置平台-Disconf.Net

    源码地址:https://github.com/qkbao/Disconf.Net 作者:青客宝  联系qq:后续奉上 为了更好的解决分布式环境下多台服务实例的配置统一管理问题,本文提出了一套完整的分 ...

  4. ASP.NET Web API 2系列(二):灵活多样的路由配置

    1. 导言 路由系统是请求消息进入ASP.NET Web API消息处理管道的第一道屏障,其根本目的在于利用注册的路由对请求的URL进行解析以确定目标HTTPController和Action的名称, ...

  5. 【CI】系列二:Ubuntu环境虚拟机安装及配置

    好了,做好了初步计划之后,如果可行性没问题,就可以开始实践了. 准备前提:VirtualBox.ubunut镜像 如果没有,可以通过如下地址下载,安装过程此处不做描述. VirtualBox 4.3. ...

  6. Azure杂七杂八系列(二) - 如何在Azure上重新配置VM

    我们经常遇到这样的问题,  对于已经建立的VM进行性能提升, 比如需要更好的虚拟机或者需要迁移到其他的虚拟网络 那么我们可以使用以下的方法进行修改. 1. 如图所示, TESTVMXX位于North ...

  7. arcgis api 3.x for js 入门开发系列二十一气泡窗口信息动态配置模板

    前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...

  8. 【转载】网站配置Https证书系列(二):IIS服务器给网站配置Https证书

    针对网站的Https证书,即SSL证书,腾讯云.阿里云都提供了免费的SSL证书申请,SSL证书申请下来后,就需要将SSL证书配置到网站中,如果网站使用的Web服务器是IIS服务器,则需要在IIS服务器 ...

  9. JBOSS EAP 6 系列五 Managed domains 管理域最主要的功能是“统一部署,统一配置”

    摘要 本文首先介绍Managed Domain的概念,管理域最主要的功能是"统一部署,统一配置".接下来通过一个实例在"统一配置"部分实现一个双机配置起来的域, ...

随机推荐

  1. Java 解析Tiff深入研究

    最近在读取客户发过来的tiff文件是,底层竟然报错了,错误:bandOffsets.length is wrong!   没办法,因为错误消息出现在tiff的read中,因此就对 底层序中tiff读取 ...

  2. Java控制台打印三角形

    for (int i = 1; i <= 5; i++) { //最上面先是五个往下一次4.3.2.1 for (int j = 5; j >= i; j--) { System.out. ...

  3. Codeforces Round #606(B-D)

    Dashboard - Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4) - Codeforces ...

  4. 实践分享!GitLab CI/CD 快速入门

    用过 GitLab 的同学肯定也对 GitLab CI/CD 不陌生,GitLab CI/CD 是一个内置在 GitLab 中的工具,它可以帮助我们在每次代码推送时运行一系列脚本来构建.测试和验证代码 ...

  5. .Net+Vue3实现数据简易导入功能

    在开发的过程中,上传文件或者导入数据是一件很常见的事情,导入数据可以有两种方式: 前端上传文件到后台,后台读取文件内容,进行验证再进行存储 前端读取数据,进行数据验证,然后发送数据到后台进行存储 这两 ...

  6. Ubuntu系统apt添加第三方PPA源

    一.前言 1.1目的 在使用Ubuntu时往往apt源会自带很多常用软件,但是大部分都是比较老的版本,本文主要是为了实现以下两个目的: 通过添加第三方的PPA源解决软件版本过低或者没有安装包的情况: ...

  7. python3实现:进程遇Error定时重启

    import os import time # 停止HFish def stopHFish(): # while True: try: # 找到HFish进程号 HFish_id = int(os.p ...

  8. TortoiseSVN 执行清理( cleanUp )失败的解决方案

    TortoiseSVN 执行清理( cleanUp )失败的解决方案 今天碰到了一个比较棘手的问题,在这里做一下记录,以方便自己和有需要的朋友在之后碰到该类问题时有个参考. 现象 更新SVN时弹出清理 ...

  9. C#,使用NPOI,导出excel文件

    /// <summary> /// 导出excel文件 /// </summary> /// <param name="dt">Table表数据 ...

  10. 【Spring】Spring bean中id和name的差异

    id和name都是spring 容器中中bean 的唯一标识符. id: 一个bean的唯一标识 , 命名格式必须符合XML ID属性的命名规范 name: 可以用特殊字符,并且一个bean可以用多个 ...