zookeeper 实战案例分享:cruator客户端编程
上两篇介绍了zookeeper服务器端的安装和配置,今天分享下利用zookeeper客户端编程来实现配置文件的统一管理,包括文件添加、删除、更新的同步。
比如,连接数据库信息的配置文件,一般每个应用服务器代码上都会存放。某个时候如果我想添加一个新数据库用户连接,那么对应用到的服务器上配置文件都要修改一遍,对于上百台的服务器,一一修改显然不现实,这时,我们可以把配置文件统一放到zookeeper服务器上,我们只需要更改zookeeper服务器上的配置文件,然后所有应用服务器上的zookeeper客户端监听到zookeeper服务器上的配置文件被改变了,进行实时同步就可以了。
主要的结构图如下:
【环境介绍】:为了看得清楚,我们这次引入两台机器,分别扮演服务器端和客户端
服务器端(liunx系统):10.126.101.153 客户端(windows): 10.249.9.19 编程环境:java+eclipse+maven+cruator
一、启动zookeeper服务(10.126.101.153)
[root@test bin]# ./zkServer.sh start
JMX enabled by default
Using config: /home/mysql/darren/software/zookeeper-3.4./bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
二、编写客户端代码(java)
由于ZooKeeper自带的客户端API太底层, 程序员在使用的时候需要自己处理很多事情,更为关键的是,使用过程中如果不当会产生很多问题,如:
- 初始化连接的问题: 在client与server之间握手建立连接的过程中, 如果握手失败, 执行所有的同步方法(比如create, getData等)将抛出异常
- 自动恢复(failover)的问题: 当client与一台server的连接丢失,并试图去连接另外一台server时, client将回到初始连接模式
- session过期的问题: 在极端情况下, 出现ZooKeeper session过期, 客户端需要自己去监听该状态并重新创建
为了方便我们编程和简化应用,这里使用cruator框架。关于cruator框架的一些介绍可以参考这里curator解决了zookeeper client哪些问题
使用cruator时,建议采用maven管理项目,maven可以为我们很容易的引入cruator依赖包,关于maven安装和配置参考这里。eclipse4.5版本以上一般都已经安装m2了,只需要配置即可。
1、采用eclipse创建maven项目
New->Other->Maven->Maven Project,然后一直默认next,填写Group Id,Artifact Id,Package,点击finish即可。
2、配置pom.xml文件,引入cruator依赖包
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.darren</groupId>
<artifactId>zk_client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>zk_client</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <dependencies> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.netflix.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>commons-daemon</groupId>
<artifactId>commons-daemon</artifactId>
<version>1.0.10</version>
</dependency>
</dependencies>
</project>
3、编写zookeeper 客户端操作代码
使用cruator编写zk客户端,一般分为以下几个步骤:
1)使用CuratorFrameworkFactory建立客户端到zookeeper服务器端的连接;
2)创建PathChildrenCache对象,表示zk路径节点及数据
3)为PathChildrenCache对象建立监听,这里需要实现PathChildrenCacheListener接口,用于处理监听事件逻辑。
代码如下:
package com.darren.zk_client; import com.netflix.curator.framework.CuratorFramework;
import com.netflix.curator.framework.CuratorFrameworkFactory;
import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
import com.netflix.curator.framework.recipes.cache.PathChildrenCacheEvent;
import com.netflix.curator.framework.recipes.cache.PathChildrenCacheListener;
import com.netflix.curator.retry.ExponentialBackoffRetry;
import com.netflix.curator.retry.RetryUntilElapsed;
import com.netflix.curator.utils.ZKPaths; public class App
{
private static final String PATH = "/db/pools"; @SuppressWarnings("resource")
public static void main( String[] args ) throws Exception
{
CuratorFramework client = null;
PathChildrenCache cache = null;
try{
//使用CuratorFrameworkFactory建立客户端到zookeeper服务器端的连接并启动
client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", new RetryUntilElapsed(3000, 1000));
client.start();
//创建PathChildrenCache对象,表示zk路径节点及数据
cache = new PathChildrenCache(client,PATH,true);
//为PathChildrenCache对象建立监听,这里需要实现PathChildrenCacheListener接口,用于处理监听事件逻辑
cache.getListenable().addListener(new Listener());
cache.start();
} catch(Exception e){ }
//表示该java程序一直运行,如果没有,每次java启动后就自动退出了
while (true) {
Thread.sleep(500);
}
} //内部类,用户实现监听接口
private static class Listener implements PathChildrenCacheListener{ @Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
// TODO Auto-generated method stub
switch (event.getType()){
case CHILD_ADDED:{
System.out.println("Node added: " + ZKPaths.getNodeFromPath(event.getData().getPath()));
break;
}
case CHILD_UPDATED:{
System.out.println("Node changed: " + ZKPaths.getNodeFromPath(event.getData().getPath()));
break;
}
case CHILD_REMOVED:{
System.out.println("Node removed: " + ZKPaths.getNodeFromPath(event.getData().getPath()));
break;
}
default:
System.out.println("no node changed!!!");
break;
}
} } }
运行效果:
2016-12-01 16:52:42,394 INFO com.netflix.curator.framework.imps.CuratorFrameworkImpl - Starting
2016-12-01 16:52:42,482 INFO org.apache.zookeeper.ZooKeeper - Client environment:zookeeper.version=3.4.5-1392090, built on 09/30/2012 17:52 GMT
2016-12-01 16:52:42,482 INFO org.apache.zookeeper.ZooKeeper - Client environment:host.name=507B9D97E083.anjuke.net
2016-12-01 16:52:42,482 INFO org.apache.zookeeper.ZooKeeper - Client environment:java.version=1.7.0_79
2016-12-01 16:52:42,482 INFO org.apache.zookeeper.ZooKeeper - Client environment:java.vendor=Oracle Corporation
2016-12-01 16:52:42,482 INFO org.apache.zookeeper.ZooKeeper - Client environment:java.home=C:\Program Files\Java\jdk1.7.0_79\jre
2016-12-01 16:52:42,482 INFO org.apache.zookeeper.ZooKeeper - Client environment:java.class.path=E:\workdir\java\zk_client\target\classes;E:\workdir\java\repo\com\netflix\curator\curator-recipes\1.3.0\curator-recipes-1.3.0.jar;E:\workdir\java\repo\com\google\guava\guava\11.0.1\guava-11.0.1.jar;E:\workdir\java\repo\com\google\code\findbugs\jsr305\1.3.9\jsr305-1.3.9.jar;E:\workdir\java\repo\com\netflix\curator\curator-framework\1.3.0\curator-framework-1.3.0.jar;E:\workdir\java\repo\com\netflix\curator\curator-client\1.3.0\curator-client-1.3.0.jar;E:\workdir\java\repo\org\apache\zookeeper\zookeeper\3.4.5\zookeeper-3.4.5.jar;E:\workdir\java\repo\org\slf4j\slf4j-api\1.6.1\slf4j-api-1.6.1.jar;E:\workdir\java\repo\org\slf4j\slf4j-log4j12\1.6.1\slf4j-log4j12-1.6.1.jar;E:\workdir\java\repo\log4j\log4j\1.2.15\log4j-1.2.15.jar;E:\workdir\java\repo\javax\mail\mail\1.4\mail-1.4.jar;E:\workdir\java\repo\javax\activation\activation\1.1\activation-1.1.jar;E:\workdir\java\repo\jline\jline\0.9.94\jline-0.9.94.jar;E:\workdir\java\repo\org\jboss\netty\netty\3.2.2.Final\netty-3.2.2.Final.jar;E:\workdir\java\repo\com\googlecode\json-simple\json-simple\1.1.1\json-simple-1.1.1.jar;E:\workdir\java\repo\commons-daemon\commons-daemon\1.0.10\commons-daemon-1.0.10.jar
2016-12-01 16:52:42,483 INFO org.apache.zookeeper.ZooKeeper - Client environment:java.library.path=C:\Program Files\Java\jdk1.7.0_79\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:/Program Files/Java/jdk1.7.0_79/bin/../jre/bin/server;C:/Program Files/Java/jdk1.7.0_79/bin/../jre/bin;C:/Program Files/Java/jdk1.7.0_79/bin/../jre/lib/amd64;C:\Program Files\Java\jdk1.7.0_79\bin;C:\Program Files\Java\jdk1.7.0_79\jre\bin;C:\Perl64\site\bin;C:\Perl64\bin;C:\Python27\;C:\Python27\Scripts;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\MIT\Kerberos\bin;C:\CygwinPortable\App\Cygwin\bin;C:\Program Files\TortoiseGit\bin;C:\Program Files\Git\cmd;D:\Program files\apache-maven-3.3.9\bin;D:\Program files\eclipse;;.
2016-12-01 16:52:42,483 INFO org.apache.zookeeper.ZooKeeper - Client environment:java.io.tmpdir=C:\Users\HAILIA~1\AppData\Local\Temp\
2016-12-01 16:52:42,483 INFO org.apache.zookeeper.ZooKeeper - Client environment:java.compiler=<NA>
2016-12-01 16:52:42,483 INFO org.apache.zookeeper.ZooKeeper - Client environment:os.name=Windows 7
2016-12-01 16:52:42,484 INFO org.apache.zookeeper.ZooKeeper - Client environment:os.arch=amd64
2016-12-01 16:52:42,484 INFO org.apache.zookeeper.ZooKeeper - Client environment:os.version=6.1
2016-12-01 16:52:42,484 INFO org.apache.zookeeper.ZooKeeper - Client environment:user.name=hailiangzhao
2016-12-01 16:52:42,484 INFO org.apache.zookeeper.ZooKeeper - Client environment:user.home=C:\Users\hailiangzhao
2016-12-01 16:52:42,484 INFO org.apache.zookeeper.ZooKeeper - Client environment:user.dir=E:\workdir\java\zk_client
2016-12-01 16:52:42,486 INFO org.apache.zookeeper.ZooKeeper - Initiating client connection, connectString=10.126.101.153:2181 sessionTimeout=60000 watcher=com.netflix.curator.ConnectionState@271816d1
2016-12-01 16:52:42,718 INFO org.apache.zookeeper.ClientCnxn - Opening socket connection to server tjtx-101-153.58os.org/10.126.101.153:2181. Will not attempt to authenticate using SASL (unknown error)
2016-12-01 16:52:42,752 INFO org.apache.zookeeper.ClientCnxn - Socket connection established to tjtx-101-153.58os.org/10.126.101.153:2181, initiating session
2016-12-01 16:52:42,796 INFO org.apache.zookeeper.ClientCnxn - Session establishment complete on server tjtx-101-153.58os.org/10.126.101.153:2181, sessionid = 0x158b95fadec0001, negotiated timeout = 40000
2016-12-01 16:52:42,801 INFO com.netflix.curator.framework.state.ConnectionStateManager - State change: CONNECTED
Node added: darren.php
上面的控制台信息表示client已经与10.126.101.153:2181 zookeeper服务端建立了连接,并且对服务器上的/db/pools节点进行了监控,只要这下面的数据有任何变化,都会输出变化的node和内容。
这时,我们可以在服务器端进行如下操作:
[zk: 10.126.101.153:(CONNECTED) ] create /db/pools/darren1.php "darren1.php"
Created /db/pools/darren1.php
[zk: 10.126.101.153:(CONNECTED) ] set /db/pools/darren1.php "xxxxxx"
cZxid = 0x7
ctime = Thu Dec :: CST
mZxid = 0x8
mtime = Thu Dec :: CST
pZxid = 0x7
cversion =
dataVersion =
aclVersion =
ephemeralOwner = 0x0
dataLength =
numChildren =
[zk: 10.126.101.153:(CONNECTED) ]
这时客户端控制台追加输出,表示已经监控到了darren1.php内容改变:
Node added: darren1.php
Node changed: darren1.php
okay,使用cruator框架编写zk客户端是不是很容易呢。
当然,这个小例子很简单,还没有进行配置文件的同步,我们可以对以上程序进行如下几个改进即可实现:
1、在处理监听事件的内部类里,我们可以对变化的节点内容写入本地文件中,实现了文件同步。
2、使用daemon接口,把该java程序封装成windows或者linux服务,永久运行,保证实时同步文件。
【遇到的错误:】
【Multiple markers at this line @Override的解决方法】http://blog.csdn.net/mazhaojuan/article/details/28931375
【maven编译时出现读取XXX时出错invalid LOC header (bad signature)】http://blog.csdn.net/woshixuye/article/details/14669929
【log4j:WARN No appenders could be found for logger】http://www.cnblogs.com/jbelial/archive/2012/06/05/2536814.html
【moven参考资料】
【maven安装配置】http://jingyan.baidu.com/article/1709ad808ad49f4634c4f00d.html
【maven profile配置】http://elim.iteye.com/blog/1900568
【maven处理资源文件】http://www.cnblogs.com/now-fighting/p/4888343.html
【maven pom.xml配置说明】http://www.cnblogs.com/qq78292959/p/3711501.html
【java参考资料】
【java api官方文档】http://docs.oracle.com/javase/7/docs/api/
【java程序以服务方式运行】http://blog.csdn.net/jason5186/article/details/9146167
【cruator参考资料】
【cruator简介】http://macrochen.iteye.com/blog/1366136/
【cruator java api】http://curator.apache.org/apidocs/index.html
【zookeeper客户端编程API】http://zookeeper.apache.org/doc/r3.4.6/javaExample.html
【cruator 案例】http://blog.sina.com.cn/s/blog_616e189f01018axz.html
zookeeper 实战案例分享:cruator客户端编程的更多相关文章
- 大数据学习day20-----spark03-----RDD编程实战案例(1 计算订单分类成交金额,2 将订单信息关联分类信息,并将这些数据存入Hbase中,3 使用Spark读取日志文件,根据Ip地址,查询地址对应的位置信息
1 RDD编程实战案例一 数据样例 字段说明: 其中cid中1代表手机,2代表家具,3代表服装 1.1 计算订单分类成交金额 需求:在给定的订单数据,根据订单的分类ID进行聚合,然后管理订单分类名称, ...
- shell脚本编程——生产实战案例
生产实战案例 在日常的生产环境中,可能会遇到需要批量检查内网目前在线的主机IP地址有哪些,还可能需要检查这些在线的主机哪些端口是开放状态,因此依靠手工来检查是可以实现,但比较费时费力,所以需要 ...
- python实战案例--银行系统
stay hungry, stay foolish.求知若饥,虚心若愚. 今天和大家分享一个python的实战案例,很多人在学习过程中都希望通过一些案例来试一下,也给自己一点动力.那么下面介绍一下这次 ...
- 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange
如何从40亿整数中找到不存在的一个 前言 给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数.(在文件中至少确实一个这样的数-为什么?).在具有足够内存的情况 ...
- 【Redis3.0.x】实战案例
Redis3.0.x 实战案例 简介 <Redis实战>的学习笔记和总结. 书籍链接 初识 Redis Redis 简介 Redis 是一个速度非常快的键值对存储数据库,它可以存储键和五种 ...
- 盘它!基于CANN的辅助驾驶AI实战案例,轻松搞定车辆检测和车距计算!
摘要:基于昇腾AI异构计算架构CANN(Compute Architecture for Neural Networks)的简易版辅助驾驶AI应用,具备车辆检测.车距计算等基本功能,作为辅助驾驶入门级 ...
- Office 2010 KMS激活原理和案例分享
Office 2010 KMS激活原理和案例分享 为了减低部署盗版(可能包含恶意软件.病毒和其他安全风险)的可能性,Office 2010面向企业客户推出了新的批量激活方式:KMS和MAK.这 ...
- Office 2010 KMS激活原理和案例分享 - Your Office Solution Here - Site Home - TechNet Blogs
[作者:葛伟华.张玉工程师 , Office/Project支持团队, 微软亚太区全球技术支持中心 ] 为了减低部署盗版(可能包含恶意软件.病毒和其他安全风险)的可能性,Office 2010面向企 ...
- JAX-RS 2.0 REST客户端编程实例
JAX-RS 2.0 REST客户端编程实例 2014/01/28 | 分类: 基础技术, 教程 | 0 条评论 | 标签: JAX-RS, RESTFUL 分享到:3 本文由 ImportNew - ...
随机推荐
- ios7中的edgesForExtendedLayout
edgesForExtendedLayout是一个类型为UIExtendedEdge的属性,指定边缘要延伸的方向. 因为iOS7鼓励全屏布局,所以它的默认值是UIRectEdgeAll——四周边缘都延 ...
- Docker镜像Export导出和Import导入
在使用Docker时最头痛的无非无法获取仓库镜像,我们可以通过Export导出镜像备份,通过import导入镜像.导出镜像是通过容器进行导出,下面来看镜像对应的容器: root@default:~# ...
- [j2ee]java中的xml操作
一.XML简单介绍 xml是可扩展标记语言,主要用来标记数据.定义数据类型,很适合万维网传输. xml特点: xml是一种标记语言.非常类似HTML xml的设计宗旨是数据传输,而不是显示数 ...
- css 用 display: inline-block; 代替 float
浮动可以将两个块级元素浮动在同一水平上.但float的缺点也有很多,还需要其他样式弥补. 早年我使用过 display: inline-block; 但苦于兼容性问题一直没敢全面使用. 近几年主要玩移 ...
- (一)spark算子 分为3大类
value类型的算子 处理数据类型为value型的算子(也就是这个算子只处理数据类型为value的数据),可以根据rdd的输入分区与输出分区的关系分为以下几个类型 (1)输入分区与输出分区一对一型 m ...
- Jquery 中Ajax使用的四种情况
<script type="text/javascript" language="javascript" src="JS/jquery-1[1] ...
- linux模块导出符号 EXPORT_SYMBOL_GPL&EXPORT_SYMBOL(转)
转自:http://blog.csdn.net/angle_birds/article/details/7396748 一个模块mod1中定义一个函数func1:在另外一个模块mod2中定义一个函数f ...
- 关于并发模型 Actor 和 CSP
最近在看<七天七并发模型>这本书,在书上介绍了 Actor 和 CSP 这两种并发模型.这两种模型很像,但还是有一些不同的地方.看完之后,比较困扰的是: 在什么场合使用哪种模型比较好呢? ...
- 从头认识java-17.5 堵塞队列(以生产者消费者模式为例)
这一章节我们来讨论一下堵塞队列.我们以下将通过生产者消费者模式来介绍堵塞队列. 1.什么是堵塞队列?(摘自于并发编程网对http://tutorials.jenkov.com/java-concurr ...
- 安装virtualBox 增强包
1 在原始操作系统安装. 2 打开USB设置. 3 运行虚拟机中的Linux中,Device->install guest additions 再安装增强包. 4 插入U盘,如果这时可以看到U盘 ...