由于zookeeper的client只有zookeeper一个对象,使用也比较简单,所以就不许要文字说明了,在代码中注释下就ok 了。

1、测试用的main方法


package ClientExample;

public class TestMain {
public static void main(String[] args) {
/*
* 测试流程
* 1、创建sever1的连接client1,并且创建一个永久性的/test节点
* 2、创建一个针对server1的临时节点
* 3、创建server2的连接client21,并创建一个针对server2的临时节点
* 4、创建server3的连接client3,并创建一个针对server3的临时节点
* 5、分别查看client1、client2、client3的三个节点的字节点数量,确定是否同步成功
* 6、修改client1的临时节点内容,然后在在client2和client3中查看
* 7、kill掉client3的线程,然后检查是watcher是否有通知给client1和client2
*/ Thread t1= new ClientThread("127.0.0.1:2181","server1",false);
Thread t2= new ClientThread("127.0.0.1:2182","server2",false);
Thread t3= new ClientThread("127.0.0.1:2183","server3",false);
Thread t4= new ClientThread("127.0.0.1:2181","server4",false); t1.start();
t2.start();
t3.start();
t4.start();
ControlThread c = new ControlThread(t1, t2, t3, t4);
c.start();
int i=0;
while(true)
{
i++;
i--; } /*
* 测试控制台输出:
* connectIP:server4,path:null,state:SyncConnected,type:None
* connectIP:server3,path:/test,state:SyncConnected,type:NodeChildrenChanged
* connectIP:server4,path:/test/server4,state:SyncConnected,type:NodeCreated
* 。。。。。。。。。。。
*
* connectIP:server2,path:null,state:Disconnected,type:None
server2exception,KeeperErrorCode = ConnectionLoss for /test
connectIP:newServer1,path:null,state:SyncConnected,type:None
connectIP:server1,path:/test,state:SyncConnected,type:NodeChildrenChanged
connectIP:server4,path:/test/server2,state:SyncConnected,type:NodeDeleted
connectIP:server4,path:/test,state:SyncConnected,type:NodeChildrenChanged
connectIP:newServer1,path:/test,state:SyncConnected,type:NodeChildrenChanged
connectIP:server3,path:/test/server2,state:SyncConnected,type:NodeDeleted
connectIP:server3,path:/test,state:SyncConnected,type:NodeChildrenChanged
*/
}
}

2、zookeeper封装的接口:


package ClientExample;

import java.io.IOException;
import java.util.List;
import org.apache.zookeeper.KeeperException;
/**
* zookeeper的操作封装接口,实现了常用的操作
* 创建、销毁、写入、修改、查询等。
* @author ransom
*
*/
public interface ServerOperation {
void init(String address,String serverName) throws IOException;
void destroy() throws InterruptedException;
List<String> getChilds(String path) throws KeeperException,
InterruptedException;
String getData(String path) throws KeeperException, InterruptedException;
void changeData(String path, String data) throws KeeperException,
InterruptedException;
void delData(String path) throws KeeperException, InterruptedException;
void apendTempNode(String path, String data) throws KeeperException,
InterruptedException;
void apendPresistentNode(String path, String data) throws KeeperException,
InterruptedException; void delNode(String path) throws KeeperException, InterruptedException;
boolean exist(String path) throws KeeperException, InterruptedException;
}

3、接口的实现:

package ClientExample;

import java.io.IOException;
import java.util.List;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
public class ServerConnector implements ServerOperation {
// 创建一个Zookeeper实例,第一个参数为目标服务器地址和端口,第二个参数为Session超时时间,第三个为节点变化时的回调方法
private ZooKeeper zk = null;
public void init(String address,String serverName) throws IOException {
zk = new ZooKeeper(address, 500000,
new MultiWatcher(serverName));
}
@Override
public void destroy() throws InterruptedException {
// TODO Auto-generated method stub
if (zk != null) {
zk.close();
}
}
@Override
public List<String> getChilds(String path) throws KeeperException, InterruptedException {
// TODO Auto-generated method stub
if (zk != null) {
return zk.getChildren(path, true);
}
return null;
}
@Override
public String getData(String path) throws KeeperException, InterruptedException {
// TODO Auto-generated method stub
if (zk != null) {
// 取得/root/childone节点下的数据,返回byte[]
byte[] b = zk.getData(path, true, null);
return new String(b);
}
return null;
}
@Override
public void changeData(String path,String data) throws KeeperException, InterruptedException {
// TODO Auto-generated method stub
if (zk != null) {
// 修改节点/root/childone下的数据,第三个参数为版本,如果是-1,那会无视被修改的数据版本,直接改掉
zk.setData(path, data.getBytes(),-1);
}
}
@Override
public void delData(String path) throws InterruptedException, KeeperException {
// TODO Auto-generated method stub
if (zk != null) {
// 删除/root/childone这个节点,第二个参数为版本,-1的话直接删除,无视版本
zk.delete(path, -1);
}
}
@Override
public void delNode(String path) throws InterruptedException, KeeperException {
// TODO Auto-generated method stub
if (zk != null) {
zk.delete(path, -1);
}
}
@Override
public boolean exist(String path) throws KeeperException,
InterruptedException {
// TODO Auto-generated method stub
if (zk != null) {
return zk.exists(path, true)!=null;
}
return false;
}
@Override
public void apendTempNode(String path, String data) throws KeeperException,
InterruptedException {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
if (zk != null)
{
// 创建一个节点root,数据是mydata,不进行ACL权限控制,节点为永久性的(即客户端shutdown了也不会消失)
/*
* 创建一个给定的目录节点 path, 并给它设置数据,
* CreateMode 标识有四种形式的目录节点,分别是
* PERSISTENT:持久化目录节点,这个目录节点存储的数据不会丢失;
* PERSISTENT_SEQUENTIAL:顺序自动编号的目录节点,这种目录节点会根据当前已近存在的节点数自动加 1,然后返回给客户端已经成功创建的目录节点名;
* EPHEMERAL:临时目录节点,一旦创建这个节点的客户端与服务器端口也就是 session 超时,这种节点会被自动删除;
* EPHEMERAL_SEQUENTIAL:临时自动编号节点
*/
zk.create(path, data.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
}
}
@Override
public void apendPresistentNode(String path, String data)
throws KeeperException, InterruptedException {
// TODO Auto-generated method stub
if (zk != null)
{
// 创建一个节点root,数据是mydata,不进行ACL权限控制,节点为永久性的(即客户端shutdown了也不会消失)
/*
* 创建一个给定的目录节点 path, 并给它设置数据,
* CreateMode 标识有四种形式的目录节点,分别是
* PERSISTENT:持久化目录节点,这个目录节点存储的数据不会丢失;
* PERSISTENT_SEQUENTIAL:顺序自动编号的目录节点,这种目录节点会根据当前已近存在的节点数自动加 1,然后返回给客户端已经成功创建的目录节点名;
* EPHEMERAL:临时目录节点,一旦创建这个节点的客户端与服务器端口也就是 session 超时,这种节点会被自动删除;
* EPHEMERAL_SEQUENTIAL:临时自动编号节点
*/
zk.create(path, data.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
}
}

4、一个控制的线程,主要用来强制kill掉连接的线程


package ClientExample;

public class ControlThread extends Thread{
public ControlThread(Thread t1,Thread t2,Thread t3,Thread t4)
{
list[0]=t1;
list[1]=t2;
list[2]=t4;
list[3]=t4;
} private Thread[] list = new Thread[4];
private int num=0;
public void run()
{
while(true)
{
if(num==7)
{
list[2].stop();
System.out.println("kill server3");
}
if(num==15)
{
list[3].stop();
System.out.println("kill server4");
}
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

5、watcher 的实现:


package ClientExample;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
/**
* 提供给多个client使用的watcher
* @author ransom
*
*/
public class MultiWatcher implements Watcher{
public MultiWatcher(String address)
{
connectAddress=address;
} private String connectAddress=null; @Override
public void process(WatchedEvent event) {
// TODO Auto-generated method stub
String outputStr="";
if(connectAddress!=null){
outputStr+="connectIP:"+connectAddress;
}
outputStr+=",path:"+event.getPath();
outputStr+=",state:"+event.getState();
outputStr+=",type:"+event.getType(); System.out.println(outputStr);
}
}

6、client 运行 的Thread


package ClientExample;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.zookeeper.KeeperException;
public class ClientThread extends Thread{
public ClientThread(String address,String serverName,boolean islog)
{
this.address=address;
this.serverName=serverName;
try {
otherOperation();
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.islog=islog;
}
private boolean islog=true;
private final String rootPath = "/test";
private String address;
private String serverName;
private ServerOperation operationCient = null; public void run()
{
if(operationCient==null)
{
System.out.println("operationCient=null");
return;
} while(true){
try {
if(islog){
System.out.println(serverName+",loopTime:"+getNowTime());
}
observerChildData(rootPath);
} catch (KeeperException e) {
// TODO Auto-generated catch block
System.out.println(serverName+"exception,"+e.getLocalizedMessage());
try {
operationCient= new ServerConnector();
operationCient.init("127.0.0.1:2181","newServer1");
} catch (IOException e1) {
// TODO Auto-generated catch block
System.out.println(serverName+" reconnect exception,"+e.getLocalizedMessage());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} } /*
* 测试流程
* 1、创建sever1的连接client1,并且创建一个永久性的/test节点
* 2、创建一个针对server1的临时节点
* 3、创建server2的连接client21,并创建一个针对server2的临时节点
* 4、创建server3的连接client3,并创建一个针对server3的临时节点
* 5、分别查看client1、client2、client3的三个节点的字节点数量,确定是否同步成功
* 6、修改client1的临时节点内容,然后在在client2和client3中查看
* 7、kill掉client3的线程,然后检查是watcher是否有通知给client1和client2
*/ private void otherOperation() throws KeeperException, InterruptedException
{
operationCient= new ServerConnector();
try {
operationCient.init(address,serverName);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} if(operationCient==null)
{
System.out.println("operationCient=null");
return;
}
if(!operationCient.exist(rootPath))
{
operationCient.apendPresistentNode(rootPath, "this node is creat by " + serverName);
} //添加临时节点
if(!operationCient.exist(rootPath+"/"+serverName))
{
operationCient.apendTempNode(rootPath+"/"+serverName, "this node is creat by " + serverName);
}
observerChildData("/test"); //修改临时节点内容
operationCient.changeData(rootPath+"/"+serverName, "this node is changed by " + serverName);
//临时节点内容
List<String> childs=operationCient.getChilds(rootPath);
for(String str : childs)
{
System.out.println("observered by "+ serverName +": child node is :"+ str);
} } //查看临时节点的同步状态
public void observerChildData(String path) throws KeeperException, InterruptedException
{
if(operationCient==null)
{
System.out.println("operationCient=null");
return;
} List<String> childs=operationCient.getChilds(rootPath);
if(islog){
System.out.println("observered by "+ serverName +": childs len is :"+ childs.size());
}
for(String str : childs)
{
if(islog){
System.out.println("observered by "+ serverName +": child node is :"+ str+",data is :"+operationCient.getData(rootPath+"/"+str));
}
} }
public String getNowTime()
{
DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
return format1.format(new Date());
} }

zookeeper 应用开发的更多相关文章

  1. zookeeper[3] zookeeper API开发注意事项总结

    如下是根据官方接口文档(http://zookeeper.apache.org/doc/r3.4.1/api/org/apache/zookeeper/ZooKeeper.html#register( ...

  2. zookeeper Eclipse 开发环境搭建及简单示例

    一,下载Zookeeper安装包 从官方网站下载稳定版安装包后,解压. 其中ZK_HOME 为:D:\Program Files\zookeeper-3.4.9 二,启动Zookeeper Serve ...

  3. Zookeeper项目开发环境搭建(Eclipse\MyEclipse + Maven)

    写在前面的话 可详细参考,一定得去看 HBase 开发环境搭建(Eclipse\MyEclipse + Maven) 我这里,相信,能看此博客的朋友,想必是有一定基础的了.我前期写了大量的基础性博文. ...

  4. 【分布式技术专题】「Zookeeper中间件」给大家学习一下Zookeeper的”开发伴侣”—Curator-Framework(基础篇)

    CuratorFramework基本介绍 CuratorFramework是Netflix公司开源的一套Zookeeper客户端框架,它作为一款优秀的ZooKeeper客户端开源工具,主要提供了对客户 ...

  5. zookeeper+dubbo-admin开发dubbo应用

    前面的章节中我们已经安装好了zookeeper,tomcat了.今天我们来实现一个完整的从dubbo消息产生到消费的完整流程. 1.dubbo api 2.dubbo consumer 消费者 3.d ...

  6. Zookeeper入门开发demo

    package CreateGroup; import java.io.IOException; import java.util.List; import java.util.concurrent. ...

  7. 分布式服务协调技术zookeeper笔记

    本文主要学习ZooKeeper的体系结构.节点类型.节点监听.常用命令等基础知识,最后还学习了ZooKeeper的高可用集群的搭建与测试.希望能给想快速掌握ZooKeeper的同学有所帮助. ZooK ...

  8. hadoop学习笔记:zookeeper学习(上)

    在前面的文章里我多次提到zookeeper对于分布式系统开发的重要性,因此对zookeeper的学习是非常必要的.本篇博文主要是讲解zookeeper的安装和zookeeper的一些基本的应用,同时我 ...

  9. 基于ZooKeeper的分布式Session实现(转)

    1.   认识ZooKeeper ZooKeeper—— “动物园管理员”.动物园里当然有好多的动物,游客可以根据动物园提供的向导图到不同的场馆观赏各种类型的动物,而不是像走在原始丛林里,心惊胆颤的被 ...

随机推荐

  1. SELinux策略语言--客体类别和许可

    1. 简介 SELinux策略语言主要描述policy.conf的相关语法,其相关部分如下图所示: 2. 客体类别 定义内核支持的客体类别和许可的策略语言指令,并对SELinux系统中内核客体类别标准 ...

  2. [csdn markdown]使用摘记一源代码高亮及图片上传和链接

    本文主要内容是体验csdn markdown的代码块高亮显示和图片链接及上传. 图片上传 上边这是标题行,只需要使用一个#就可以表示,几个表示是几级标题 图片上传 本地图片上传控件 本地图片上传方式 ...

  3. iOS集合视图单元格高亮和选中的区别

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交 ...

  4. 剑指offer面试题4 替换空格(c)

  5. 关于activitygroup过时,用frament替换操作

    现在Fragment的应用真的是越来越广泛了,之前Android在3.0版本加入Fragment的时候,主要是为了解决Android Pad屏幕比较大,空间不能充分利用的问题,但现在即使只是在手机上, ...

  6. Android事件总线EventBus详解

    顾名思义,AndroidEventBus是一个Android平台的事件总线框架,它简化了Activity.Fragment.Service等组件之间的交互,很大程度上降低了它们之间的耦合,使我们的代码 ...

  7. 【一天一道LeetCode】#242. Valid Anagram

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given t ...

  8. MariaDB存储引擎

    MariaDB存储引擎 存储引擎就是指表的类型.数据库的存储引擎决定了表在计算机中的存储方式.存储引擎的概念是MariaDB的特点,而且是一种插入式的存储引擎概念.这决定了MariaDB数据库中的表可 ...

  9. TCP/IP入门(2) --网络层

    /** 本篇博客由 126(127不可用) 2^24 -2 B 2^14 -1 128.1 191.255 2^16 -2 C 2^21 -1 192.0.1 223.255.255 2^8 -2 D ...

  10. Java:函数,类,数组之间的运用

    在我的demoe类中,我实现了以下方法: 这个类在另外一个文件,demoe.java中 public class Demoe { //计算一个数字因子的个数 public static int get ...