zookeeper虚拟机使用和java api使用zookeeper案例

zookeeper动物园管理员

中间件,提供协调服务

作用于分布式系统,发挥其优势,可以为大数据服务

支持java,提供java和c语言的客户端api

什么是分布式系统?

很多台计算机组成一个整体,一个整体一致对外并且处理同一请求

内部的每台计算机都可以相互通信(rest/rpc)

客户端到服务端的一次请求到相应结束会经历多台计算机

zoopkeeper的特性

一致性:数据一致性,数据按照顺序分批入库

原子性:事务要么成功要么失败,不会局部化

单一视图:客户端连接集群中任一zk节点,数据都是一致性的

可靠性:每次对zk的操作状态都会保存在服务端

实时性:客户端可以读取到zk服务端的最新数据

jdk的安装

下载linux的jsk1.8.tar,上传至linux服务器

解压缩jdk,配置jdk

测试:java -version

单机zookeeper安装

zookeeper下载,安装以及配置环境变量

zookeeper文件夹主要目录介绍

zookeeper配置文件介绍,运行zk

zoo.cfg配置

tickTime:用于计算时间单元。比如session超时:N*tickTime

initLimit:用于集群,允许从节点连接并同步到master节点的初始化连接时间,以tickTime的倍数来表示

syncLimit:用于集群,master主节点与从节点之间发消息,请求和应答时间长度(心跳机制)

dataDir:必须配置

dataLogDir:日志目录。如果不能配置会和dataDir公用

clientPort:连接服务器的端口,默认2181

zookeeper基本数据模型介绍

是一个树形结构,类似于前端开发中的tree.js组件

zk的数据模型也可以理解为linux/unix的文件目录:/usr/local/..

每一个节点都称为znode,它可以有子节点,也可以有数据

每个节点分为临时节点和永久节点,临时节点在客户端断开后消失

每个zk节点都有各自的版本号,可以通过命令行来显示节点信息

每当节点数据发生改变,那么该节点版本号会累加(乐观锁)

删除/修改过时节点,版本号不匹配则会报错

每个zk节点存储的税局不宜过大,几k即可

节点可以设置权限acl,可以通过权限来限制用户的访问

zookeeper数据模型的基本操作

客户端连接

./zkServer.sh start

./zkCli.sh

查看znode结构

关闭客户端连接

zookeeper的作用体现

maser节点选举,主节点挂了以后,从节点就会接收工作,并且保证这个节点但是唯一的,这就是所谓的首脑模式,从而保证我们的集群是高可用的。

发布与订阅,雷氏消息队列MQ(amq,rmq,),dubbo发布者把数据存在znode上,订阅者会读取这个数据

提供分布式锁,分布式环境中不同进程之间争资源,类似于多线程中的锁

统一配置文件管理,即只需要部署一台服务器,则可以把相同的配置文件同步更新到其他所有服务器,此操作在云计算机中用的特别多

集群管理,集群中保证数据的强一致性

zk特性-session的基本原理

客户端与服务端之间的连接存在会话

每个会话都可以设置一个超时时间

心跳结束,session则过期

session过期,则临时节点znide会被抛弃

心跳机制:客户端向服务端的ping包请求

zk常用命令

通过./zkCli.sh打开zk的客户端进行命令行后台

ls与ls2命令

get与stat命令

create命令

create -e /imooc/tmp 无序

create -s /imooc/sec seq 顺序

set命令(改变dataVersion)

set /imooc data-imooc 1(跟版本号的需要最新版本号)

delete命令

和set一样不带版本号能执行,带版本号就要最新的版本号

zk特性-watcher的基本原理

针对每个节点的操作,都会有一个监督者->watcher

当监控的某个对象(znode)发生了变化,则触发watcher时间

zk中的watcher是一次性的,触发后立即销毁

父节点,子节点 增删改都能触发器watcher

针对不同类型的操作,触发的watcher时间也不同:

1.(子)节点创建事件

2.(子)节点删除事件

3.(子)节点数据变化事件

stat /test watch

get /test watch

父节点触发事件

创建父节点触发

WATCHER::
Created /test
WatchedEvent state:SyncConnected type:NodeCreated path:/test

修改父节点触发

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/imooccZxid = 0x4

删除父节点触发

WATCHER::

WatchedEvent state:SyncConnected type:NodeDeleted path:/test

子节点触发事件

创建子节点触发父节点watch事件

WATCHER::Created /imooc/abc

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/imooc

删除子节点触发父节点watch事件

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/imooc

修改子节点不会触发父节点watch事件

watcher的使用场景

统一资源配置

acl权限控制

针对节点可以设置相关读写等权限,目的为了保障数据安全性

权限permissions可以指定不同的权限范围以及角色

acl命令行

getAcl:获取某个节点的acl权限信息

setAcl:设置某个节点的acl权限信息

addauth:输入认证授权信息,注册时输入明文密码(登录)

但是在zk的系统里,密码是以加密的形式存在

Acl的构成

zk的acl通过[scheme🆔permissions]来构成权限列表

scheme:代表采用的某种权限机制

id:代表允许访问的用户

permissions:权限组合字符串

'world,'anyone
cdrwa

world:world下只有一个id,即只有一个用户,也就是anyone,那么组合的写法就是world:anyone:[permissions]

auth:代表认证登录,需要注册用户有权限就可以,形式为auth:user:password:[permissions]

digest:需要对密码加密才能访问,组合形式为digest:username:BASE64(SHA1(password)):[permissions]

简而言之auth与digest区别就是,前者明文,后者密文,

setAcl /path auth:lee:cdrwa与setAcl /path digest:lee:BASE64(SHA1(password))cdrwa是等价的,在通过addauth digest lee:lee 后都能操作指定节点的权限

ip:当设置为ip指定的ip地址,此时限制ip进行访问,比如ip:192.168.1.1:[permissions]

super:代表超级管理员,拥有所有的权限

权限字符串缩写crdwa

create:创建子节点

read:获取节点/子节点

write:设置节点数据

delete:删除子节点

admin设置权限

acl命令行

setAcl /imooc/abc/aaa world:anyone:wadc

setAcl /names auth:imooc:imooc:crwda

setAcl /imooc/test digest:imooc:XwEDaL3J0JQGkRQzM0DpO6zMzZs=:racd

setAcl /imooc/ip ip:192.168.0.103:cdwar

addauth digest imooc:imooc (登录是明文)

super

1、修改zkServer.sh增加super管理员

2、重启zkServer.sh

ACL使用场景

生产/测试环境分离,开发者无权操作测试库的节点,只能看

生产环境上控制指定ip的服务可以访问相关节点,防止混乱

zk四字命令

zk可以通过它自身提供的简写命令来和服务器进行交互

需要使用到nc命令,安装yum install nc

echo[commond] | nc [ip] [port]

stat 查看zk的状态信息,以及是否mode

ruok查看当前zkserver是否启动,返回imok

dump列出未经处理的会话和临时节点

conf查看服务器配置

cons展示连接到服务器的客户端信息

envi环境变量

mntr监控zk健康信息

wchs展示watch的信息

wchc与wchp session与watch及path与watch信息,watch节点与会话对应信息(配置文件后面加4lw.commands.whitelist=*才能用)

zk集群

单机伪分布式

配置数据文件 dataDir/myid 1/2/3 对应server.1/2/3

server.1=192.168.0.108:2888:3888通信端口:选举端口
server.2=192.168.0.108:2889:3889
server.3=192.168.0.108:2890:3890

通过./zkCli.sh -server [ip]:[port]检测集群是否配置成功

三台虚拟机zk集群

server.1=192.168.0.107:2888:3888
server.2=192.168.0.108:2888:3888
server.3=192.168.0.109:2888:3888

记得关闭防火墙systemctl stop firewalld.service

zookeeper原生java api使用

会话连接与恢复

package com.imooc.zk.demo;

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Title: ZKConnectDemo.java
 * @Package com.imooc.zk.demo
 * @Description: zookeeper 连接demo演示
 */
public class ZKConnect implements Watcher {
		
	final static Logger log = LoggerFactory.getLogger(ZKConnect.class);

	public static final String zkServerPath = "192.168.1.110:2181";
//	public static final String zkServerPath = "192.168.1.111:2181,192.168.1.111:2182,192.168.1.111:2183";
	public static final Integer timeout = 5000;
	
	public static void main(String[] args) throws Exception {
		/**
		 * 客户端和zk服务端链接是一个异步的过程
		 * 当连接成功后后,客户端会收的一个watch通知
		 * 
		 * 参数:
		 * connectString:连接服务器的ip字符串,
		 * 		比如: "192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181"
		 * 		可以是一个ip,也可以是多个ip,一个ip代表单机,多个ip代表集群
		 * 		也可以在ip后加路径
		 * sessionTimeout:超时时间,心跳收不到了,那就超时
		 * watcher:通知事件,如果有对应的事件触发,则会收到一个通知;如果不需要,那就设置为null
		 * canBeReadOnly:可读,当这个物理机节点断开后,还是可以读到数据的,只是不能写,
		 * 					       此时数据被读取到的可能是旧数据,此处建议设置为false,不推荐使用
		 * sessionId:会话的id
		 * sessionPasswd:会话密码	当会话丢失后,可以依据 sessionId 和 sessionPasswd 重新获取会话
		 */
		ZooKeeper zk = new ZooKeeper(zkServerPath, timeout, new ZKConnect());
		
		log.warn("客户端开始连接zookeeper服务器...");
		log.warn("连接状态:{}", zk.getState());
		
		new Thread().sleep(2000);
		
		log.warn("连接状态:{}", zk.getState());
	}

	@Override
	public void process(WatchedEvent event) {
		log.warn("接受到watch通知:{}", event);
	}
}


package com.imooc.zk.demo;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * @Title: ZKConnectDemo.java
 * @Description: zookeeper 恢复之前的会话连接demo演示
 */
public class ZKConnectSessionWatcher implements Watcher {
	
	final static Logger log = LoggerFactory.getLogger(ZKConnectSessionWatcher.class);

	public static final String zkServerPath = "192.168.1.110:2181";
	public static final Integer timeout = 5000;
	
	public static void main(String[] args) throws Exception {
		
		ZooKeeper zk = new ZooKeeper(zkServerPath, timeout, new ZKConnectSessionWatcher());
		
		long sessionId = zk.getSessionId();
		String ssid = "0x" + Long.toHexString(sessionId);
		System.out.println(ssid);
		byte[] sessionPassword = zk.getSessionPasswd();
		
		log.warn("客户端开始连接zookeeper服务器...");
		log.warn("连接状态:{}", zk.getState());
		new Thread().sleep(1000);
		log.warn("连接状态:{}", zk.getState());
		
		new Thread().sleep(200);
		
		// 开始会话重连
		log.warn("开始会话重连...");
		
		ZooKeeper zkSession = new ZooKeeper(zkServerPath, 
											timeout, 
											new ZKConnectSessionWatcher(), 
											sessionId, 
											sessionPassword);
		log.warn("重新连接状态zkSession:{}", zkSession.getState());
		new Thread().sleep(1000);
		log.warn("重新连接状态zkSession:{}", zkSession.getState());
	}
	
	@Override
	public void process(WatchedEvent event) {
		log.warn("接受到watch通知:{}", event);
	}
}


节点的增删改查

同步创建和异步创建、删除节点

package com.imooc.zk.demo;

import java.io.IOException;
import java.util.List;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;

/**
 * 
 * @Title: ZKConnectDemo.java
 * @Description: zookeeper 操作demo演示
 */
public class ZKNodeOperator implements Watcher {

	private ZooKeeper zookeeper = null;
	
	public static final String zkServerPath = "192.168.1.110:2181";
	public static final Integer timeout = 5000;
	
	public ZKNodeOperator() {}
	
	public ZKNodeOperator(String connectString) {
		try {
			zookeeper = new ZooKeeper(connectString, timeout, new ZKNodeOperator());
		} catch (IOException e) {
			e.printStackTrace();
			if (zookeeper != null) {
				try {
					zookeeper.close();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 
	 * @Title: ZKOperatorDemo.java
	 * @Description: 创建zk节点
	 */
	public void createZKNode(String path, byte[] data, List<ACL> acls) {
		
		String result = "";
		try {
			/**
			 * 同步或者异步创建节点,都不支持子节点的递归创建,异步有一个callback函数
			 * 参数:
			 * path:创建的路径
			 * data:存储的数据的byte[]
			 * acl:控制权限策略
			 * 			Ids.OPEN_ACL_UNSAFE --> world:anyone:cdrwa
			 * 			CREATOR_ALL_ACL --> auth:user:password:cdrwa
			 * createMode:节点类型, 是一个枚举
			 * 			PERSISTENT:持久节点
			 * 			PERSISTENT_SEQUENTIAL:持久顺序节点
			 * 			EPHEMERAL:临时节点
			 * 			EPHEMERAL_SEQUENTIAL:临时顺序节点
			 */
			result = zookeeper.create(path, data, acls, CreateMode.PERSISTENT);
			
//			String ctx = "{'create':'success'}";
//			zookeeper.create(path, data, acls, CreateMode.PERSISTENT, new CreateCallBack(), ctx);
			
			System.out.println("创建节点:\t" + result + "\t成功...");
			new Thread().sleep(2000);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws Exception {
		ZKNodeOperator zkServer = new ZKNodeOperator(zkServerPath);
		
		// 创建zk节点
//		zkServer.createZKNode("/testnode", "testnode".getBytes(), Ids.OPEN_ACL_UNSAFE);
		
		/**
		 * 参数:
		 * path:节点路径
		 * data:数据
		 * version:数据状态
		 */
//		Stat status  = zkServer.getZookeeper().setData("/testnode", "xyz".getBytes(), 2);
//		System.out.println(status.getVersion());
		
		/**
		 * 参数:
		 * path:节点路径
		 * version:数据状态
		 */
		zkServer.createZKNode("/test-delete-node", "123".getBytes(), Ids.OPEN_ACL_UNSAFE);
//		zkServer.getZookeeper().delete("/test-delete-node", 2);
		
		String ctx = "{'delete':'success'}";
		zkServer.getZookeeper().delete("/test-delete-node", 0, new DeleteCallBack(), ctx);
		Thread.sleep(2000);
	}

	public ZooKeeper getZookeeper() {
		return zookeeper;
	}
	public void setZookeeper(ZooKeeper zookeeper) {
		this.zookeeper = zookeeper;
	}

	@Override
	public void process(WatchedEvent event) {
	}
}


package com.imooc.zk.demo;


import org.apache.zookeeper.AsyncCallback.StringCallback;

public class CreateCallBack implements StringCallback {

	@Override
	public void processResult(int rc, String path, Object ctx, String name) {
		System.out.println("创建节点: " + path);
		System.out.println((String)ctx);
	}

}

package com.imooc.zk.demo;


import org.apache.zookeeper.AsyncCallback.VoidCallback;

public class DeleteCallBack implements VoidCallback {
	@Override
	public void processResult(int rc, String path, Object ctx) {
		System.out.println("删除节点" + path);
		System.out.println((String)ctx);
	}

}

countDownLatch的使用

他是一个计数器

多用于线程,可以暂停也可以继续

.await() .countDown()

案例

package com.imooc.countdown;

import java.util.concurrent.CountDownLatch;

/**
 * 抽象类,用于演示 危险品化工车监控中心 统一检查
 */
public abstract class DangerCenter implements Runnable {

	private CountDownLatch countDown;		// 计数器
	private String station;					// 调度站
	private boolean ok;						// 调度站针对当前自己的站点进行检查,是否检查ok的标志
	
	public DangerCenter(CountDownLatch countDown, String station) {
		this.countDown = countDown;
		this.station = station;
		this.ok = false;
	}

	@Override
	public void run() {
		try {
			check();
			ok = true;
		} catch (Exception e) {
			e.printStackTrace();
			ok = false;
		} finally {
			if (countDown != null) {
				countDown.countDown();
			}
		}
	}

	/**
	 * 检查危化品车
	 * 蒸罐
	 * 汽油
	 * 轮胎
	 * gps
	 * ...
	 */
	public abstract void check();

	public CountDownLatch getCountDown() {
		return countDown;
	}
	public void setCountDown(CountDownLatch countDown) {
		this.countDown = countDown;
	}
	public String getStation() {
		return station;
	}
	public void setStation(String station) {
		this.station = station;
	}
	public boolean isOk() {
		return ok;
	}
	public void setOk(boolean ok) {
		this.ok = ok;
	}
	
}

package com.imooc.countdown;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class CheckStartUp {

	private static List<DangerCenter> stationList;
	private static CountDownLatch countDown;
	
	public CheckStartUp() {
	}
	
	public static boolean checkAllStations() throws Exception {

		// 初始化3个调度站
		countDown = new CountDownLatch(3);
		
		// 把所有站点添加进list
		stationList = new ArrayList<>();
		stationList.add(new StationBeijingIMooc(countDown));
		stationList.add(new StationJiangsuSanling(countDown));
		stationList.add(new StationShandongChangchuan(countDown));
		
		// 使用线程池
		Executor executor = Executors.newFixedThreadPool(stationList.size());
		
		for (DangerCenter center : stationList) {
			executor.execute(center);
		}
		
		// 等待线程执行完毕
		countDown.await();
		
		for (DangerCenter center : stationList) {
			if (!center.isOk()) {
				return false;
			}
		}
		
		return true;
	}
	
	public static void main(String[] args) throws Exception {
		boolean result = CheckStartUp.checkAllStations();
		System.out.println("监控中心针对所有危化品调度站点的检查结果为:" + result);
	}

}

package com.imooc.countdown;

import java.util.concurrent.CountDownLatch;

public class StationBeijingIMooc extends DangerCenter {

	public StationBeijingIMooc(CountDownLatch countDown) {
		super(countDown, "北京慕课调度站");
	}

	@Override
	public void check() {
		System.out.println("正在检查 [" + this.getStation() + "]...");
		
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("检查 [" + this.getStation() + "] 完毕,可以发车~");
	}

}

package com.imooc.countdown;

import java.util.concurrent.CountDownLatch;

public class StationJiangsuSanling extends DangerCenter {

	public StationJiangsuSanling(CountDownLatch countDown) {
		super(countDown, "江苏三林调度站");
	}

	@Override
	public void check() {
		System.out.println("正在检查 [" + this.getStation() + "]...");
		
		try {
			Thread.sleep(1500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("检查 [" + this.getStation() + "] 完毕,可以发车~");
	}

}

package com.imooc.countdown;

import java.util.concurrent.CountDownLatch;

public class StationShandongChangchuan extends DangerCenter {

	public StationShandongChangchuan(CountDownLatch countDown) {
		super(countDown, "山东长川调度站");
	}

	@Override
	public void check() {
		System.out.println("正在检查 [" + this.getStation() + "]...");
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("检查 [" + this.getStation() + "] 完毕,可以发车~");
	}

}

原生java api节点查询

获取节点数据

package com.imooc.zk.demo;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

/**
 * 
 * @Description: zookeeper 获取节点数据的demo演示
 */
public class ZKGetNodeData implements Watcher {

	private ZooKeeper zookeeper = null;
	
	public static final String zkServerPath = "192.168.1.110:2181";
	public static final Integer timeout = 5000;
	private static Stat stat = new Stat();
	
	public ZKGetNodeData() {}
	
	public ZKGetNodeData(String connectString) {
		try {
			zookeeper = new ZooKeeper(connectString, timeout, new ZKGetNodeData());
		} catch (IOException e) {
			e.printStackTrace();
			if (zookeeper != null) {
				try {
					zookeeper.close();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	
	private static CountDownLatch countDown = new CountDownLatch(1);
	
	public static void main(String[] args) throws Exception {
	
		ZKGetNodeData zkServer = new ZKGetNodeData(zkServerPath);
		
		/**
		 * 参数:
		 * path:节点路径
		 * watch:true或者false,注册一个watch事件
		 * stat:状态
		 */
		byte[] resByte = zkServer.getZookeeper().getData("/imooc", true, stat);
		String result = new String(resByte);
		System.out.println("当前值:" + result);
		countDown.await();
	}
	
	@Override
	public void process(WatchedEvent event) {
		try {
			if(event.getType() == EventType.NodeDataChanged){
				ZKGetNodeData zkServer = new ZKGetNodeData(zkServerPath);
				byte[] resByte = zkServer.getZookeeper().getData("/imooc", false, stat);
				String result = new String(resByte);
				System.out.println("更改后的值:" + result);
				System.out.println("版本号变化dversion:" + stat.getVersion());
				countDown.countDown();
			} else if(event.getType() == EventType.NodeCreated) {
				
			} else if(event.getType() == EventType.NodeChildrenChanged) {
				
			} else if(event.getType() == EventType.NodeDeleted) {
				
			} 
		} catch (KeeperException e) { 
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public ZooKeeper getZookeeper() {
		return zookeeper;
	}
	public void setZookeeper(ZooKeeper zookeeper) {
		this.zookeeper = zookeeper;
	}
}

获取子节点数据

package com.imooc.zk.demo;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.EventType;

/**
 * @Description: zookeeper 获取子节点数据的demo演示
 */
public class ZKGetChildrenList implements Watcher {

	private ZooKeeper zookeeper = null;
	
	public static final String zkServerPath = "192.168.1.110:2181";
	public static final Integer timeout = 5000;
	
	public ZKGetChildrenList() {}
	
	public ZKGetChildrenList(String connectString) {
		try {
			zookeeper = new ZooKeeper(connectString, timeout, new ZKGetChildrenList());
		} catch (IOException e) {
			e.printStackTrace();
			if (zookeeper != null) {
				try {
					zookeeper.close();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	
	private static CountDownLatch countDown = new CountDownLatch(1);
	
	public static void main(String[] args) throws Exception {
	
		ZKGetChildrenList zkServer = new ZKGetChildrenList(zkServerPath);
		
		/**
		 * 参数:
		 * path:父节点路径
		 * watch:true或者false,注册一个watch事件
		 */
//		List<String> strChildList = zkServer.getZookeeper().getChildren("/imooc", true);
//		for (String s : strChildList) {
//			System.out.println(s);
//		}
		
		// 异步调用
		String ctx = "{'callback':'ChildrenCallback'}";
//		zkServer.getZookeeper().getChildren("/imooc", true, new ChildrenCallBack(), ctx);
		zkServer.getZookeeper().getChildren("/imooc", true, new Children2CallBack(), ctx);
		
		countDown.await();
	}
	
	@Override
	public void process(WatchedEvent event) {
		try {
			if(event.getType()==EventType.NodeChildrenChanged){
				System.out.println("NodeChildrenChanged");
				ZKGetChildrenList zkServer = new ZKGetChildrenList(zkServerPath);
				List<String> strChildList = zkServer.getZookeeper().getChildren(event.getPath(), false);
				for (String s : strChildList) {
					System.out.println(s);
				}
				countDown.countDown();
			} else if(event.getType() == EventType.NodeCreated) {
				System.out.println("NodeCreated");
			} else if(event.getType() == EventType.NodeDataChanged) {
				System.out.println("NodeDataChanged");
			} else if(event.getType() == EventType.NodeDeleted) {
				System.out.println("NodeDeleted");
			} 
		} catch (KeeperException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public ZooKeeper getZookeeper() {
		return zookeeper;
	}
	public void setZookeeper(ZooKeeper zookeeper) {
		this.zookeeper = zookeeper;
	}
	
}


package com.imooc.zk.demo;


import java.util.List;

import org.apache.zookeeper.AsyncCallback.Children2Callback;
import org.apache.zookeeper.data.Stat;

public class Children2CallBack implements Children2Callback {

	@Override
	public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
		for (String s : children) {
			System.out.println(s);
		}
		System.out.println("ChildrenCallback:" + path);
		System.out.println((String)ctx);	
		System.out.println(stat.toString());
	}


}

package com.imooc.zk.demo;


import java.util.List;

import org.apache.zookeeper.AsyncCallback.ChildrenCallback;

public class ChildrenCallBack implements ChildrenCallback {

	@Override
	public void processResult(int rc, String path, Object ctx, List<String> children) {
		for (String s : children) {
			System.out.println(s);
		}
		System.out.println("ChildrenCallback:" + path);
		System.out.println((String)ctx);	
	}

}

判断节点是否存在

package com.imooc.zk.demo;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

/**
 * @Description: zookeeper 判断阶段是否存在demo
 */
public class ZKNodeExist implements Watcher {

	private ZooKeeper zookeeper = null;
	
	public static final String zkServerPath = "192.168.1.110:2181";
	public static final Integer timeout = 5000;
	
	public ZKNodeExist() {}
	
	public ZKNodeExist(String connectString) {
		try {
			zookeeper = new ZooKeeper(connectString, timeout, new ZKNodeExist());
		} catch (IOException e) {
			e.printStackTrace();
			if (zookeeper != null) {
				try {
					zookeeper.close();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	
	private static CountDownLatch countDown = new CountDownLatch(1);
	
	public static void main(String[] args) throws Exception {
	
		ZKNodeExist zkServer = new ZKNodeExist(zkServerPath);
		
		/**
		 * 参数:
		 * path:节点路径
		 * watch:watch与节点是否存在无关
		 */
		Stat stat = zkServer.getZookeeper().exists("/imooc-fake", true);
		if (stat != null) {
			System.out.println("查询的节点版本为dataVersion:" + stat.getVersion());
		} else {
			System.out.println("该节点不存在...");
		}
		
		countDown.await();
	}
	
	@Override
	public void process(WatchedEvent event) {
		if (event.getType() == EventType.NodeCreated) {
			System.out.println("节点创建");
			countDown.countDown();
		} else if (event.getType() == EventType.NodeDataChanged) {
			System.out.println("节点数据改变");
			countDown.countDown();
		} else if (event.getType() == EventType.NodeDeleted) {
			System.out.println("节点删除");
			countDown.countDown();
		}
	}
	
	public ZooKeeper getZookeeper() {
		return zookeeper;
	}
	public void setZookeeper(ZooKeeper zookeeper) {
		this.zookeeper = zookeeper;
	}
}


watch与acl的相关操作

package com.imooc.zk.demo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooDefs.Perms;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.apache.zookeeper.data.Stat;

import com.imooc.utils.AclUtils;

/**
 * 
 * @Description: zookeeper 操作节点acl演示
 */
public class ZKNodeAcl implements Watcher {

	private ZooKeeper zookeeper = null;
	
	public static final String zkServerPath = "192.168.1.110:2181";
	public static final Integer timeout = 5000;
	
	public ZKNodeAcl() {}
	
	public ZKNodeAcl(String connectString) {
		try {
			zookeeper = new ZooKeeper(connectString, timeout, new ZKNodeAcl());
		} catch (IOException e) {
			e.printStackTrace();
			if (zookeeper != null) {
				try {
					zookeeper.close();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	
	public void createZKNode(String path, byte[] data, List<ACL> acls) {
		
		String result = "";
		try {
			/**
			 * 同步或者异步创建节点,都不支持子节点的递归创建,异步有一个callback函数
			 * 参数:
			 * path:创建的路径
			 * data:存储的数据的byte[]
			 * acl:控制权限策略
			 * 			Ids.OPEN_ACL_UNSAFE --> world:anyone:cdrwa
			 * 			CREATOR_ALL_ACL --> auth:user:password:cdrwa
			 * createMode:节点类型, 是一个枚举
			 * 			PERSISTENT:持久节点
			 * 			PERSISTENT_SEQUENTIAL:持久顺序节点
			 * 			EPHEMERAL:临时节点
			 * 			EPHEMERAL_SEQUENTIAL:临时顺序节点
			 */
			result = zookeeper.create(path, data, acls, CreateMode.PERSISTENT);
			System.out.println("创建节点:\t" + result + "\t成功...");
		} catch (KeeperException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} 
	}
	
	public static void main(String[] args) throws Exception {
	
		ZKNodeAcl zkServer = new ZKNodeAcl(zkServerPath);
		
		/**
		 * ======================  创建node start  ======================  
		 */
		// acl 任何人都可以访问
//		zkServer.createZKNode("/aclimooc", "test".getBytes(), Ids.OPEN_ACL_UNSAFE);
		
		// 自定义用户认证访问
//		List<ACL> acls = new ArrayList<ACL>();
//		Id imooc1 = new Id("digest", AclUtils.getDigestUserPwd("imooc1:123456"));
//		Id imooc2 = new Id("digest", AclUtils.getDigestUserPwd("imooc2:123456"));
//		acls.add(new ACL(Perms.ALL, imooc1));
//		acls.add(new ACL(Perms.READ, imooc2));
//		acls.add(new ACL(Perms.DELETE | Perms.CREATE, imooc2));
//		zkServer.createZKNode("/aclimooc/testdigest", "testdigest".getBytes(), acls);
		
		// 注册过的用户必须通过addAuthInfo才能操作节点,参考命令行 addauth
//		zkServer.getZookeeper().addAuthInfo("digest", "imooc1:123456".getBytes());
//		zkServer.createZKNode("/aclimooc/testdigest/childtest", "childtest".getBytes(), Ids.CREATOR_ALL_ACL);
//		Stat stat = new Stat();
//		byte[] data = zkServer.getZookeeper().getData("/aclimooc/testdigest", false, stat);
//		System.out.println(new String(data));
//		zkServer.getZookeeper().setData("/aclimooc/testdigest", "now".getBytes(), 1);
		
		// ip方式的acl
//		List<ACL> aclsIP = new ArrayList<ACL>();
//		Id ipId1 = new Id("ip", "192.168.1.6");
//		aclsIP.add(new ACL(Perms.ALL, ipId1));
//		zkServer.createZKNode("/aclimooc/iptest6", "iptest".getBytes(), aclsIP);

		// 验证ip是否有权限
		zkServer.getZookeeper().setData("/aclimooc/iptest6", "now".getBytes(), 1);
		Stat stat = new Stat();
		byte[] data = zkServer.getZookeeper().getData("/aclimooc/iptest6", false, stat);
		System.out.println(new String(data));
		System.out.println(stat.getVersion());
	}

	public ZooKeeper getZookeeper() {
		return zookeeper;
	}
	public void setZookeeper(ZooKeeper zookeeper) {
		this.zookeeper = zookeeper;
	}

	@Override
	public void process(WatchedEvent event) {
		
	}
}


posted @   开源遗迹  阅读(86)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
历史上的今天:
2022-02-14 暴力匹配字符串
2022-02-14 动态规划算法
2022-02-14 分治算法介绍
点击右上角即可分享
微信分享提示