前面介绍了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. UOJ#XX A+B Problem (罔烙硫)

    题面 背景 题目描述 从前有个 n n n 个方格排成一行,从左至右依此编号为 1 , 2 , ⋯ , n 1,2,⋯,n 1,2,⋯,n. 有一天思考熊想给这 n n n 个方格染上黑白两色. 第 ...

  2. Android 自动取色并设置沉浸式状态栏

    Android 自动取色并设置沉浸式状态栏 - Stars-One的杂货小窝 最近在进行产品的优化,也是研究了下沉浸式状态栏的实现方法及自动取色,记录一下笔记 设置沉浸式状态栏 1.添加依赖 这里,是 ...

  3. 【MySQL】从入门到精通7-设计多对多数据库

    上期:[MySQL]从入门到精通6-MySQL数据类型与官方文档 第一章:理解 和一对多不一样,多对多意思是,一个数据可以被不同的数据关联. 如果是一对多,我们还可以用外键来达成. 但是现在我们是多对 ...

  4. python自学笔记10:while循环和for循环

    条件控制和循环控制是两种典型的流程控制方法,前面我们写了 if 条件控制,这节讲 for 循环和 while 循环. 循环是另一种控制流程的方式,一个循环体中的代码在程序中只需要编写一次,但可能会连续 ...

  5. awk5个使用场景

    awk简介 首先要知道awk的使用场景,需了解awk有哪些优势与短板. 关于个人近期学习awk总结其优势: awk对文本的处理运算效率同比其他工具效率高很多(比shell的for循环高10倍以上,运算 ...

  6. openstack中Cinder组件简解

    一,Cinder组件介绍 概念 cinder组件作用: 块存储服务,为运行实例提供稳定的数据块存储服务 块存储服务,提供对 volume 从创建到删除整个生命周期的管理 二,常用操作 1.Volume ...

  7. Springboot shiro JWT集成总结

    SpringBoot Shiro JWT 1.建表 DDL.sql CREATE TABLE `t_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, ` ...

  8. FreeSql 导入数据的各种场景总结 [C#.NET ORM]

    前言 导入数据这种脏活.累活,相信大家多多少少都有经历,常见的场景有: 同服务器从A表导数据到B表 批量导入新数据 批量新增或更新数据 跨服务器从A表导数据到B表 每种场景有自己的特点,我们一般会根据 ...

  9. 2020年12月-第02阶段-前端基础-CSS Day06

    CSS Day06 定位(position) 理解 能说出为什么要用定位 能说出定位的4种分类 能说出四种定位的各自特点 能说出我们为什么常用子绝父相布局 应用 能写出淘宝轮播图布局 1. CSS 布 ...

  10. .NET 7 来了!!!

    .NET 7 首个RC(发布候选)版本 最近 .Net 的大事件,就是微软发布了.NET 7的首个RC(发布候选)版本,而据微软发布的消息,这是 .NET 7 的最后一个预览版,下一个版本将是第一个候 ...