上两篇介绍了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客户端编程的更多相关文章

  1. 大数据学习day20-----spark03-----RDD编程实战案例(1 计算订单分类成交金额,2 将订单信息关联分类信息,并将这些数据存入Hbase中,3 使用Spark读取日志文件,根据Ip地址,查询地址对应的位置信息

    1 RDD编程实战案例一 数据样例 字段说明: 其中cid中1代表手机,2代表家具,3代表服装 1.1 计算订单分类成交金额 需求:在给定的订单数据,根据订单的分类ID进行聚合,然后管理订单分类名称, ...

  2. shell脚本编程——生产实战案例

    生产实战案例     在日常的生产环境中,可能会遇到需要批量检查内网目前在线的主机IP地址有哪些,还可能需要检查这些在线的主机哪些端口是开放状态,因此依靠手工来检查是可以实现,但比较费时费力,所以需要 ...

  3. python实战案例--银行系统

    stay hungry, stay foolish.求知若饥,虚心若愚. 今天和大家分享一个python的实战案例,很多人在学习过程中都希望通过一些案例来试一下,也给自己一点动力.那么下面介绍一下这次 ...

  4. 如何从40亿整数中找到不存在的一个 webservice Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库 WPF实战案例-打印 RabbitMQ与.net core(五) topic类型 与 headers类型 的Exchange

    如何从40亿整数中找到不存在的一个 前言 给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数.(在文件中至少确实一个这样的数-为什么?).在具有足够内存的情况 ...

  5. 【Redis3.0.x】实战案例

    Redis3.0.x 实战案例 简介 <Redis实战>的学习笔记和总结. 书籍链接 初识 Redis Redis 简介 Redis 是一个速度非常快的键值对存储数据库,它可以存储键和五种 ...

  6. 盘它!基于CANN的辅助驾驶AI实战案例,轻松搞定车辆检测和车距计算!

    摘要:基于昇腾AI异构计算架构CANN(Compute Architecture for Neural Networks)的简易版辅助驾驶AI应用,具备车辆检测.车距计算等基本功能,作为辅助驾驶入门级 ...

  7. Office 2010 KMS激活原理和案例分享

    Office 2010 KMS激活原理和案例分享     为了减低部署盗版(可能包含恶意软件.病毒和其他安全风险)的可能性,Office 2010面向企业客户推出了新的批量激活方式:KMS和MAK.这 ...

  8. Office 2010 KMS激活原理和案例分享 - Your Office Solution Here - Site Home - TechNet Blogs

    [作者:葛伟华.张玉工程师 ,  Office/Project支持团队, 微软亚太区全球技术支持中心 ] 为了减低部署盗版(可能包含恶意软件.病毒和其他安全风险)的可能性,Office 2010面向企 ...

  9. JAX-RS 2.0 REST客户端编程实例

    JAX-RS 2.0 REST客户端编程实例 2014/01/28 | 分类: 基础技术, 教程 | 0 条评论 | 标签: JAX-RS, RESTFUL 分享到:3 本文由 ImportNew - ...

随机推荐

  1. mysql学习笔记(编辑中)

    1.LAST_INSERT_ID()依赖于当前服务器会话中自动产生的序列编号.同时括号中也可以赋值更新数据,eg: update test set id = last_insert_id(id+10) ...

  2. 对象序列和反序列化Xml

    1. XmlArray和XmlArrayItem XmlArray和XmlArrayItem是不同的,XmlArray是指这个数组叫什么,XmlArrayItem 值数组的每个元素叫什么. <X ...

  3. Quartus和ISE调用Synplify进行综合的问题

    分别尝试采用Quartus和ISE调用第三方综合软件Synplify进行综合. [软件版本] Quartus II 13.0 (SP).ISE 14.4 .Synplify 201303. [问题描述 ...

  4. Android OOM的解决方式

    尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图. 由于这些函数在完毕decode后,终于都是通过ja ...

  5. 基于日志处理的ElasticSearch的学(gen)习(feng)

    最近学了点solr,然后有听说了ElasticSearch,就想着也学一下ElasticSearch,然后看见了ElasticSearch用于日志的收集的分析,这里就来学习一下. 百度一下Elasti ...

  6. 使用strace,lstrace,truss来跟踪程序的运行过程

    使用truss.strace或ltrace诊断软件问题 2008-07-05 16:25 使用truss.strace或ltrace诊断软件问题          进程无法启动,软件运行速度突然变慢, ...

  7. 三层登录实例VB.NET版具体解释---理论加实战篇

    层,百度百科这样解释,首先-重叠起来的东西:重叠起来的东西中的一部分:层次|表层|大气层.其次-重叠.反复:层峦叠嶂|层出不穷.最后-量词,用于能够分出层次的事物.女孩儿强烈的第六感,三层中的层一定是 ...

  8. IP地址、子网掩码、网关的关系

    网络管理中的IP地址.子网掩码和网关是每个网管必须要掌握的基础知识,只有掌握它,才能够真正理解TCP/IP协议的设置.以下我们就来深入浅出地讲解什么是子网掩码. IP地址的结构 要想理解什么是子网掩码 ...

  9. C语言基础知识【数据类型】

    C 数据类型1.在 C 语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统.变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式.2.C 中的类型可分为以下几种:序号    类 ...

  10. windows常用dos命令

    常用命令: d: 回车   磁盘切换 dir: 查看该目录下所有的文件和文件夹: md: 创建文件加 rd: 删除目录 cd: 进入指定的目录 cd..:回退到上级目录 cd\  :回退到根目录 de ...