一端不停的更新配置,另一端监听这个配置的变化。

    需要注意的是:监听端不一定读取到所有的变化。在zk服务器发送通知到客户端,客户端读取数据注册监听之间可能发生了多次数据变化,这些数据变化是得不到通知的。但可以保证的是每次通知得到的数据都是比之前的数据要新的。
 
ZKUtils.java
package config;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
public class ZKUtils {
/**
* 构建zookeeper客户端对象
* @param hosts
* @return
* @throws Exception
*/
public static ZooKeeper open(String hosts) throws Exception {
final CountDownLatch singal = new CountDownLatch(1); ZooKeeper zk = new ZooKeeper(hosts, 2000, new Watcher() {
@Override
public void process(WatchedEvent event) {
singal.countDown();
}
}); singal.await(); return zk;
}
}

  

ConfigUpdater.java

package config;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
/**
* 不停的更新/test节点上的数据, 模拟配置更新
*
*/
public class ConfigUpdater {
public static final String HOSTS = "hadoop1:2181";
public static final String PATH = "/test"; public static void main(String[] args) throws Exception {
ZooKeeper zk = ZKUtils.open(HOSTS); while(true) {
String data = UUID.randomUUID().toString(); Stat stat = zk.exists(PATH, false);
if(stat == null) {
zk.create(PATH, data.getBytes("UTF-8"), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} else {
zk.setData(PATH, data.getBytes("UTF-8"), -1);
} TimeUnit.SECONDS.sleep(5);
}
}
}

  

ConfigUpdateWatcher .java

package config;
import java.util.concurrent.TimeUnit;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
/**
* 注册监听/test节点上的数据变化
*
*/
public class ConfigUpdateWatcher implements Watcher {
private ZooKeeper zk = null; public ConfigUpdateWatcher() {
try {
zk = ZKUtils.open(ConfigUpdater.HOSTS);
} catch (Exception e) {
e.printStackTrace();
}
} @Override
public void process(WatchedEvent event) {
System.out.println(event); if(event.getType().equals(EventType.NodeDataChanged)) {
try {
//读取事件后, 再次注册数据监听事件
byte[] data = zk.getData(ConfigUpdater.PATH, this, null);
System.out.printf("接收到了事件%s, 新的数据是:%s", EventType.NodeDataChanged, new String(data, "UTF-8"));
System.out.println();
} catch (Exception e) {
e.printStackTrace();
}
}
} private void run() {
try {
//注册数据变化监听
zk.getData(ConfigUpdater.PATH, this, null);
} catch (Exception e) {
e.printStackTrace();
} try {
TimeUnit.SECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} public static void main(String[] args) {
new ConfigUpdateWatcher().run();
}
}

  

完善

在操作zookeeper的时候,如果是幂等操作(多次操作不影响结果),在失败时可以多次重试以增加可靠性,比如ConfigUpdater的写操作可以进行多次重试,修改后的代码如下:
package config;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
/**
* 不停的更新/test节点上的数据, 模拟配置更新
*
*/
public class ConfigUpdater {
public static final String HOSTS = "hadoop1:2181";
public static final String PATH = "/test";
public static final int RETRIES = 3; //重试次数
public static final int RETRY_PERIOD = 500; //重试间隔 public static void main(String[] args) throws Exception {
ZooKeeper zk = ZKUtils.open(HOSTS); //不停的模拟数据更新操作
while(true) { String data = UUID.randomUUID().toString(); /*
* 多次重试,增加可靠性
*/
int retied = 0;
while(true) {
try {
Stat stat = zk.exists(PATH, false);
if(stat == null) {
zk.create(PATH, data.getBytes("UTF-8"), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
} else {
zk.setData(PATH, data.getBytes("UTF-8"), -1);
} //执行成功则跳出循环,否则继续(重试)
break;
} catch (KeeperException e) {
retied++; //如果会话过期了则重新创建一个ZooKeeper客户端对象
if(e.code().equals(KeeperException.Code.SESSIONEXPIRED)) {
zk = ZKUtils.open(HOSTS);
} else {
//其他KeeperException Code的处理 //KeeperException.Code.CONNECTIONLOSS异常可以不用处理:ZooKeeper客户端对象会自动进行重新连接
} //可以重试3次,每次间隔500毫秒
if(retied == RETRIES) {
throw e;
} else {
TimeUnit.MICROSECONDS.sleep(RETRY_PERIOD);
}
}
} //模拟其他操作占用的时间
TimeUnit.SECONDS.sleep(5);
}
}
}

  

zookeeper应用 - 配置服务的更多相关文章

  1. ZooKeeper系列1:ZooKeeper的配置

    问题导读:1.zookeeper有哪些配置文件?2.zookeeper最低配置需要哪些配置项?3.zookeeper高级配置需要配置哪些项? ZooKeeper 的功能特性通过 ZooKeeper 配 ...

  2. ZooKeeper学习第二期--ZooKeeper安装配置

    一.Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式. ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境:■ 伪集群模式:就是在一台物 ...

  3. [转载] zookeeper 分布式锁服务

    转载自http://www.cnblogs.com/shanyou/archive/2012/09/22/2697818.html 分布式锁服务在大家的项目中或许用的不多,因为大家都把排他放在数据库那 ...

  4. dubbo+zookeeper+springboot构建服务

    本次和大家分享的是dubbo框架应用的初略配置和zookeeper注册中心的使用:说到注册中心现在我使用过的只有两种:zookeeper和Eureka,zk我结合dubbo来使用,而Eureka结合s ...

  5. Zookeeper系列一:Zookeeper介绍、Zookeeper安装配置、ZK Shell的使用

    https://www.cnblogs.com/leeSmall/p/9563547.html 一.Zookeeper介绍 1. 介绍Zookeeper之前先来介绍一下分布式 1.1 分布式主要是下面 ...

  6. ZooKeeper: 简介, 配置及运维指南

    1. 概览 ZooKeeper是一个供其它分布式应用程序使用的软件, 它为其它分布式应用程序提供所谓的协调服务. 所谓的协调服务, 是指ZooKeeper的如下能力 naming 命名 configu ...

  7. 【Zookeeper系列】ZooKeeper安装配置(转)

    原文链接:https://www.cnblogs.com/sunddenly/p/4018459.html 一.Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪 ...

  8. Zookeeper系列四:Zookeeper实现分布式锁、Zookeeper实现配置中心

    一.Zookeeper实现分布式锁 分布式锁主要用于在分布式环境中保证数据的一致性. 包括跨进程.跨机器.跨网络导致共享资源不一致的问题. 1. 分布式锁的实现思路 说明: 这种实现会有一个缺点,即当 ...

  9. 【转载】ZooKeeper学习第二期--ZooKeeper安装配置

    原文地址(https://www.cnblogs.com/sunddenly/p/4018459.html) 一.Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及 ...

随机推荐

  1. 可调试Windows服务框架

    参考: Build A Windows Service Framework 新建ServiceFramework类库,项目中需引用: using System.Configuration.Instal ...

  2. iphoneX 适配

    1.iphoneX的尺寸  375*812   上边有44px的危险区,下边有34px的危险区,剩下的是安全区. 2.viewport设值cover <meta name="viewp ...

  3. Chapter 3 Phenomenon——5

    I saw several things simultaneously. 我同时看见了几件事情. Nothing was moving in slow motion,the way it does i ...

  4. 编写dimgr脚本学到的知识及技巧

    编写dimgr是为了管理手机上的镜像,在此总结下过程中学到的知识及技巧(不讨论具体用法). 参数处理 以往处理脚本参数直接用循环加判断语句,若是脚本只有简单参数,这无疑是简便可行的方法.但当需要处理复 ...

  5. C#合并两个Dictionary的方法

    直接代码: public Dictionary<string, string> MergeDictionary(Dictionary<string, string> first ...

  6. Java并发编程笔记之ThreadLocalRandom源码分析

    JDK 并发包中 ThreadLocalRandom 类原理剖析,经常使用的随机数生成器 Random 类的原理是什么?及其局限性是什么?ThreadLocalRandom 是如何利用 ThreadL ...

  7. 打包命令tar

    tar是linux下最常用的打包命令,使用tar打出来的包我们常称为tar包,tar包文件的命令通常都是以.tar结尾的,也有.gz或.bz2结尾的. 1 常用参数 -c,--create # 新建打 ...

  8. 笔记四:python乱码深度剖析二

    一:学习内容 获取更改系统编码 判断字符的编码类型 文件存储和读取的编码 二:获取更改系统编码 1. 获取系统编码 import sys print sys.getdefaultencoding() ...

  9. SpringMvc注解开发

    1.四大注解的定义 (1)Controller注解:该注解使用在一个类上面,参数为value,值为访问该controller的名称,默认为空,如果为空 则值为该controller类名的首字母小写的值 ...

  10. RabbitMQ上手记录–part 2 - 安装RabbitMQ

    上一篇<<RabbitMQ 上手记录-part 1>>介绍了一些基础知识,整理了一些基础概念.接下来整理一些安装步骤和遇到的问题. 我在CentOS7和Ubuntu16.4上都 ...