zookeeper-pp

一、zookeeper简介说明

​ 重启zookeeper时需要关闭防火墙????

​ 与eclipse集成的管理zookeeper的工具:

​ 在eclipse点击help,然后点击install new software,点击add,输入名称和网址,网址是:

​ http://www.massedynamic.org/eclipse/updates/

1、什么是zookeeper

在这里插入图片描述

2、zookeeper的结构

​ zookeeper会维护一个具有层次关系的数据结构,它非常类似于一个标准的文件系统(树状结构)

3、zookeeper组成

​ zk server根据其身份特性分为三种:leader,Follower,Observer,其中Follower和Observer又统称为Learner(学习者)

​ Leader:负责客户端的writer类型请求

​ Follower:负责客户端的reader类型请求,参与leader选举等

​ Observer:特殊的“Follower”,其可以接受客户端reader请求,但不参与选举。(监控者)

4、zookeeper的应用场景

​ 配置管理

​ 集群管理

​ 发布与订阅

​ 数据库切换

​ 分布式日志的收集

​ 分布式锁、队列管理等等

二、搭建zookeeper与配置文件说明

1、步骤

​ ①、将zookeeper-3.4.5.tar.gz上传到linux的devsoft目录下

​ ②、解压到/usr/local下

​ 命令:tar -zxvf zookeeper-3.4.5.tar.gz -C /usr/local/

​ ③、重命名,在 /usr/local/目录下操作

​ mv zookeeper-3.4.5 zookeeper

​ ④、修改环境变量:vi /etc/profile

		export ZOOKEEPER_HOME=/usr/local/zookeeper

		export PATH=.:$ZOOKEEPER_HOME/bin:$JAVA_HOME/...

​ ⑤、刷新

​ source /etc/profile

​ ⑥、到zookeeper下修改配置文件

​ cd /usr/local/zookeeper/conf

​ mv zoo_sample.cfg zoo.cfg

​ ⑦、修改conf: vi zoo.cfg 修改两处

​ (1)dataDir=/usr/local/zookeeper/data

​ (2)最后面添加

​ server.0=192.168.1.103:2888:3888

​ server.1=192.168.1.104:2888:3888

​ server.2=192.168.1.105:2888:3888

​ ⑧、服务器标识配置:

​ 创建文件夹:mkdir data

​ 创建文件myid并填写内容为0,1,2:对应上一步的0,1,2(vi myid)

​ ⑨、启动zookeeper:

​ 路径:/usr/local/zookeeper/bin

​ 执行:zkServer.sh start(注意:这三台机器都要进行启动)

​ 状态:zkServer.sh status(在三个节点上检查zk的mode,一个leader和两个follower)

2、zookeeper客户端操作命令

​ zkCli.sh 进入zookeeper客户端

​ 各级提示命令进行操作

​ 查找:ls / ls /zookeeper

​ 创建并赋值:create /lptxyl zkp

​ 获取:get /lptxyl

​ 设置:set /lptxyl lipeng

​ 可以看到zookeeper集群的数据一致性

​ 递归删除节点:rmr /path

​ 删除指定某个节点:delete /path/child

​ 创建节点有两种类型:短暂(ephemeral)持久(persistent)

3、zoo.cfg详解

    tickTime:	基本事件单元,以毫秒为单位。这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,
    			也就是每隔 tickTime时间就会发送一个心跳。
    			
    dataDir:	存储内存中数据库快照的位置,顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
   
    clientPort: 这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
    
    initLimit:	这个配置项是用来配置 Zookeeper 接受客户端初始化连接时最长能忍受多少个心跳时间间隔数,
    			当已经超过 10 个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,
    			那么表明这个客户端连接失败。总的时间长度就是 10*2000=20 秒。
    
    syncLimit:	这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,
    			最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 5*2000=10 秒
    
    server.A = B:C:D : 
    			A表示这个是第几号服务器,
    			B 是这个服务器的 ip 地址;
    			C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;
    			D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader

三、java操作zookeeper

1、原生API

package com.lptxyl.zookeeper.base;

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.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;

public class ZookeeperBase {

	//zookeeper的地址
	static final String CONNECT_ADDR = "192.168.1.103:2181,192.168.1.104:2181,192.168.1.105:2181";
	//session超时时间
	static final int SESSION_OUTTIME = 5000; //ms
	//阻塞程序执行,用于等待zookeeper连接成功,发送成功信号
	static final CountDownLatch connectedSemaphore = new CountDownLatch(1);
	static final CountDownLatch connectedSemaphore2 = new CountDownLatch(1);
	public static void main(String[] args) throws Exception {
		ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher() {
			
			@Override
			public void process(WatchedEvent event) {
				//获取事件的状态
				KeeperState keeperState = event.getState();
				EventType eventType = event.getType();
				//如果是建立连接
				if(KeeperState.SyncConnected == keeperState){
					if(EventType.None == eventType){
						//如果建立连接成功,则发送信号量,让后续阻塞程序向下执行
						connectedSemaphore.countDown();
						System.out.println("zk 建立连接");
					}
				}
			}
		});
		
		//进行阻塞
		connectedSemaphore.await();
		
		System.out.println("..");
		//同步创建父节点,此外还有异步的一些方法
		/**
			参数一:节点路径,不允许递归创建节点,也就是没有父节点不能创建子节点
			参数二:节点内容,不支持序列化
			参数三:节点权限,用Ids.OPEN_ACL_UNSAFE就行
			参数四:节点类型
					CreateMode.PERSISTENT表示创建的节点是持久化的
					CreateMode.PERSISTENT_SEQUENTIAL表示持久顺序节点,有顺序的
					CreateMode.EPHEMERAL表示创建的节点是临时的,本次会话有效
					CreateMode.EPHEMERAL_SEQUENTIAL表示临时顺序节点
		*/
		zk.create("/testRoot", "testRoot".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		
		//创建子节点
//		zk.create("/testRoot/children", "children data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		
		//获取节点洗信息
//		byte[] data = zk.getData("/testRoot", false, null);
//		System.out.println(new String(data));
//		System.out.println(zk.getChildren("/testRoot", false));
		
		//修改节点的值
//		zk.setData("/testRoot", "modify data root".getBytes(), -1);
//		byte[] data = zk.getData("/testRoot", false, null);
//		System.out.println(new String(data));		
		
		//判断节点是否存在
//		System.out.println(zk.exists("/testRoot/children", false));
		//删除节点,-1这个参数表示版本号,如果是-1,则表示全部删除,不管哪个版本
//		zk.delete("/testRoot/children", -1);
//		System.out.println(zk.exists("/testRoot/children", false));
		
		zk.close();
	}
	
}

​ 创建临时节点可以实现分布式锁,因为如果两个客户端同时访问zookeeper的同一个节点,那么他们的顺序是

​ 先创建一个临时节点,然后操作,再关闭本次会话。而临时节点如果一旦创建了,就不能创建名字相同的节点

​ ,所以其他客户端不能操作本节点,而临时节点在会话关闭后会自动消失,此时另一个客户端就可以操作这个

​ 节点了

2、watch机制核心讲解

​ zookeeper有watch事件,是一次性触发的,当watch监视的数据发生变化时,通知设置了该watch的

​ client,即watcher

​ 同样,其watcher是监听数据发生了某些变化,那就一定会有对应的事件类型和状态类型

​ 事件类型:(znode节点相关的)

​ EventType.NodeCreated

​ EventType.NodeDataChanged

​ EventType.NodeChildrenChanged

​ EventType.NodeDeleted

​ 状态类型:(是跟客户端实例相关的)

​ KeeperState.Disconnected

​ KeeperState.SyncConnected

​ KeeperState.AuthFailed

​ KeeperState.Expired

​ 代码在zookeeper项目里面

package com.lptxyl.zookeeper.watch;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

/**
 * Zookeeper Wathcher 
 * 本类就是一个Watcher类(实现了org.apache.zookeeper.Watcher类)
 * @author(alienware)
 * @since 2015-6-14
 */
public class ZookeeperWatch implements Watcher {

	/** 定义原子变量 */
	AtomicInteger seq = new AtomicInteger();
	/** 定义session失效时间 */
	private static final int SESSION_TIMEOUT = 10000;
	/** zookeeper服务器地址 */
	private static final String CONNECTION_ADDR = "192.168.1.103:2181,192.168.1.104:2181,192.168.1.105:2181";
	/** zk父路径设置 */
	private static final String PARENT_PATH = "/p";
	/** zk子路径设置 */
	private static final String CHILDREN_PATH = "/p/c";
	/** 进入标识 */
	private static final String LOG_PREFIX_OF_MAIN = "【Main】";
	/** zk变量 */
	private ZooKeeper zk = null;
	/**用于等待zookeeper连接建立之后 通知阻塞程序继续向下执行 */
	private CountDownLatch connectedSemaphore = new CountDownLatch(1);

	/**
	 * 创建ZK连接
	 * @param connectAddr ZK服务器地址列表
	 * @param sessionTimeout Session超时时间
	 */
	public void createConnection(String connectAddr, int sessionTimeout) {
		this.releaseConnection();
		try {
			//this表示把当前对象进行传递到其中去(也就是在主函数里实例化的new ZooKeeperWatcher()实例对象)
			zk = new ZooKeeper(connectAddr, sessionTimeout, this);
			System.out.println(LOG_PREFIX_OF_MAIN + "开始连接ZK服务器");
			connectedSemaphore.await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 关闭ZK连接
	 */
	public void releaseConnection() {
		if (this.zk != null) {
			try {
				this.zk.close();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 创建节点
	 * @param path 节点路径
	 * @param data 数据内容
	 * @return 
	 */
	public boolean createPath(String path, String data, boolean needWatch) {
		try {
			//设置监控(由于zookeeper的监控都是一次性的所以 每次必须设置监控)
			this.zk.exists(path, needWatch);
			System.out.println(LOG_PREFIX_OF_MAIN + "节点创建成功, Path: " + 
							   this.zk.create(	/**路径*/ 
									   			path, 
									   			/**数据*/
									   			data.getBytes(), 
									   			/**所有可见*/
								   				Ids.OPEN_ACL_UNSAFE, 
								   				/**永久存储*/
								   				CreateMode.PERSISTENT ) + 	
							   ", content: " + data);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 读取指定节点数据内容
	 * @param path 节点路径
	 * @return
	 */
	public String readData(String path, boolean needWatch) {
		try {
			System.out.println("读取数据操作...");
			return new String(this.zk.getData(path, needWatch, null));
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
	}

	/**
	 * 更新指定节点数据内容
	 * @param path 节点路径
	 * @param data 数据内容
	 * @return
	 */
	public boolean writeData(String path, String data) {
		try {
			System.out.println(LOG_PREFIX_OF_MAIN + "更新数据成功,path:" + path + ", stat: " +
								this.zk.setData(path, data.getBytes(), -1));
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 删除指定节点
	 * 
	 * @param path
	 *            节点path
	 */
	public void deleteNode(String path) {
		try {
			this.zk.delete(path, -1);
			System.out.println(LOG_PREFIX_OF_MAIN + "删除节点成功,path:" + path);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 判断指定节点是否存在
	 * @param path 节点路径
	 */
	public Stat exists(String path, boolean needWatch) {
		try {
			return this.zk.exists(path, needWatch);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获取子节点
	 * @param path 节点路径
	 */
	private List<String> getChildren(String path, boolean needWatch) {
		try {
			System.out.println("读取子节点操作...");
			return this.zk.getChildren(path, needWatch);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 删除所有节点
	 */
	public void deleteAllTestPath(boolean needWatch) {
		if(this.exists(CHILDREN_PATH, needWatch) != null){
			this.deleteNode(CHILDREN_PATH);
		}
		if(this.exists(PARENT_PATH, needWatch) != null){
			this.deleteNode(PARENT_PATH);
		}		
	}
	
	/**
	 * 收到来自Server的Watcher通知后的处理。
	 */
	@Override
	public void process(WatchedEvent event) {
		
		System.out.println("进入 process 。。。。。event = " + event);
		
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		if (event == null) {
			return;
		}
		
		// 连接状态
		KeeperState keeperState = event.getState();
		// 事件类型
		EventType eventType = event.getType();
		// 受影响的path
		String path = event.getPath();
		//原子对象seq 记录进入process的次数
		String logPrefix = "【Watcher-" + this.seq.incrementAndGet() + "】";

		System.out.println(logPrefix + "收到Watcher通知");
		System.out.println(logPrefix + "连接状态:\t" + keeperState.toString());
		System.out.println(logPrefix + "事件类型:\t" + eventType.toString());

		if (KeeperState.SyncConnected == keeperState) {
			// 成功连接上ZK服务器
			if (EventType.None == eventType) {
				System.out.println(logPrefix + "成功连接上ZK服务器");
				connectedSemaphore.countDown();
			} 
			//创建节点
			else if (EventType.NodeCreated == eventType) {
				System.out.println(logPrefix + "节点创建");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} 
			//更新节点
			else if (EventType.NodeDataChanged == eventType) {
				System.out.println(logPrefix + "节点数据更新");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} 
			//更新子节点
			else if (EventType.NodeChildrenChanged == eventType) {
				System.out.println(logPrefix + "子节点变更");
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} 
			//删除节点
			else if (EventType.NodeDeleted == eventType) {
				System.out.println(logPrefix + "节点 " + path + " 被删除");
			}
			else ;
		} 
		else if (KeeperState.Disconnected == keeperState) {
			System.out.println(logPrefix + "与ZK服务器断开连接");
		} 
		else if (KeeperState.AuthFailed == keeperState) {
			System.out.println(logPrefix + "权限检查失败");
		} 
		else if (KeeperState.Expired == keeperState) {
			System.out.println(logPrefix + "会话失效");
		}
		else ;

		System.out.println("--------------------------------------------");

	}

	/**
	 * <B>方法名称:</B>测试zookeeper监控<BR>
	 * <B>概要说明:</B>主要测试watch功能<BR>
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {

		//建立watcher //当前客户端可以称为一个watcher 观察者角色
		ZookeeperWatch zkWatch = new ZookeeperWatch();
		//创建连接 
		zkWatch.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);
		//System.out.println(zkWatch.zk.toString());
		
		Thread.sleep(1000);
		
		// 清理节点
		zkWatch.deleteAllTestPath(false);
		
		//-----------------第一步: 创建父节点 /p ------------------------//
		if (zkWatch.createPath(PARENT_PATH, System.currentTimeMillis() + "", true)) {
			
			Thread.sleep(1000);
			
			//-----------------第二步: 读取节点 /p 和    读取/p节点下的子节点(getChildren)的区别 --------------//
			// 读取数据
//			zkWatch.readData(PARENT_PATH, true);
//		
//			// 读取子节点(监控childNodeChange事件)
			zkWatch.getChildren(PARENT_PATH, true);
//
//			// 更新数据
//			zkWatch.writeData(PARENT_PATH, System.currentTimeMillis() + "");
//			
			Thread.sleep(1000);
//			// 创建子节点
//			zkWatch.createPath(CHILDREN_PATH, System.currentTimeMillis() + "", true);
			
			
			//-----------------第三步: 建立子节点的触发 --------------//
//			zkWatch.createPath(CHILDREN_PATH + "/c1", System.currentTimeMillis() + "", true);
//			zkWatch.createPath(CHILDREN_PATH + "/c1/c2", System.currentTimeMillis() + "", true);
			
			//-----------------第四步: 更新子节点数据的触发 --------------//
			//在进行修改之前,我们需要watch一下这个节点:
//			Thread.sleep(1000);
//			zkWatch.readData(CHILDREN_PATH, true);
//			zkWatch.writeData(CHILDREN_PATH, System.currentTimeMillis() + "");
			
		}
		
//		Thread.sleep(10000);
		// 清理节点
//		zkWatch.deleteAllTestPath(false);
		
		
//		Thread.sleep(10000);
		zkWatch.releaseConnection();
		
	}

}

3、安全认证

​ 当一个客户端连接zookeeper的某个节点时,如果指定了一个权限认证(相当于密码)

​ (zk.addAuthInfo(authentication_type,correctAuthentication.getBytes());),那么另外一个客户端连

​ 接此节点操作数据时,也需要同样的指定这个认证的权限(相当于密码)

​ ZK提供了三种模式:权限模式,授权对象,权限

在这里插入图片描述

​ 代码如下:

package com.lptxyl.zookeeper.auth;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
/**
 * Zookeeper 节点授权
 * @author(alienware)
 * @since 2015-6-14
 */
public class ZookeeperAuth implements Watcher {

	/** 连接地址 */
	final static String CONNECT_ADDR = "192.168.1.103:2181";
	/** 测试路径 */
	final static String PATH = "/testAuth";
	final static String PATH_DEL = "/testAuth/delNode";
	/** 认证类型 */
	final static String authentication_type = "digest";
	/** 认证正确方法 */
	final static String correctAuthentication = "123456";
	/** 认证错误方法 */
	final static String badAuthentication = "654321";
	
	static ZooKeeper zk = null;
	/** 计时器 */
	AtomicInteger seq = new AtomicInteger();
	/** 标识 */
	private static final String LOG_PREFIX_OF_MAIN = "【Main】";
	
	private CountDownLatch connectedSemaphore = new CountDownLatch(1);
	
	@Override
	public void process(WatchedEvent event) {
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if (event==null) {
			return;
		}
		// 连接状态
		KeeperState keeperState = event.getState();
		// 事件类型
		EventType eventType = event.getType();
		// 受影响的path
		String path = event.getPath();
		
		String logPrefix = "【Watcher-" + this.seq.incrementAndGet() + "】";

		System.out.println(logPrefix + "收到Watcher通知");
		System.out.println(logPrefix + "连接状态:\t" + keeperState.toString());
		System.out.println(logPrefix + "事件类型:\t" + eventType.toString());
		if (KeeperState.SyncConnected == keeperState) {
			// 成功连接上ZK服务器
			if (EventType.None == eventType) {
				System.out.println(logPrefix + "成功连接上ZK服务器");
				connectedSemaphore.countDown();
			} 
		} else if (KeeperState.Disconnected == keeperState) {
			System.out.println(logPrefix + "与ZK服务器断开连接");
		} else if (KeeperState.AuthFailed == keeperState) {
			System.out.println(logPrefix + "权限检查失败");
		} else if (KeeperState.Expired == keeperState) {
			System.out.println(logPrefix + "会话失效");
		}
		System.out.println("--------------------------------------------");
	}
	/**
	 * 创建ZK连接
	 * 
	 * @param connectString
	 *            ZK服务器地址列表
	 * @param sessionTimeout
	 *            Session超时时间
	 */
	public void createConnection(String connectString, int sessionTimeout) {
		this.releaseConnection();
		try {
			zk = new ZooKeeper(connectString, sessionTimeout, this);
			//添加节点授权
			zk.addAuthInfo(authentication_type,correctAuthentication.getBytes());
			System.out.println(LOG_PREFIX_OF_MAIN + "开始连接ZK服务器");
			//倒数等待
			connectedSemaphore.await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 关闭ZK连接
	 */
	public void releaseConnection() {
		if (this.zk!=null) {
			try {
				this.zk.close();
			} catch (InterruptedException e) {
			}
		}
	}
	
	/**
	 * 
	 * <B>方法名称:</B>测试函数<BR>
	 * <B>概要说明:</B>测试认证<BR>
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		
		ZookeeperAuth testAuth = new ZookeeperAuth();
		testAuth.createConnection(CONNECT_ADDR,2000);
		List<ACL> acls = new ArrayList<ACL>(1);
		for (ACL ids_acl : Ids.CREATOR_ALL_ACL) {
			acls.add(ids_acl);
		}

		try {
			zk.create(PATH, "init content".getBytes(), acls, CreateMode.PERSISTENT);
			System.out.println("使用授权key:" + correctAuthentication + "创建节点:"+ PATH + ", 初始内容是: init content");
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			zk.create(PATH_DEL, "will be deleted! ".getBytes(), acls, CreateMode.PERSISTENT);
			System.out.println("使用授权key:" + correctAuthentication + "创建节点:"+ PATH_DEL + ", 初始内容是: init content");
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 获取数据
		getDataByNoAuthentication();
		getDataByBadAuthentication();
		getDataByCorrectAuthentication();

		// 更新数据
		updateDataByNoAuthentication();
		updateDataByBadAuthentication();
		updateDataByCorrectAuthentication();

		// 删除数据
		deleteNodeByBadAuthentication();
		deleteNodeByNoAuthentication();
		deleteNodeByCorrectAuthentication();
		//
		Thread.sleep(1000);
		
		deleteParent();
		//释放连接
		testAuth.releaseConnection();
	}
	/** 获取数据:采用错误的密码 */
	static void getDataByBadAuthentication() {
		String prefix = "[使用错误的授权信息]";
		try {
			ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null);
			//授权
			badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());
			Thread.sleep(2000);
			System.out.println(prefix + "获取数据:" + PATH);
			System.out.println(prefix + "成功获取数据:" + badzk.getData(PATH, false, null));
		} catch (Exception e) {
			System.err.println(prefix + "获取数据失败,原因:" + e.getMessage());
		}
	}

	/** 获取数据:不采用密码 */
	static void getDataByNoAuthentication() {
		String prefix = "[不使用任何授权信息]";
		try {
			System.out.println(prefix + "获取数据:" + PATH);
			ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null);
			Thread.sleep(2000);
			System.out.println(prefix + "成功获取数据:" + nozk.getData(PATH, false, null));
		} catch (Exception e) {
			System.err.println(prefix + "获取数据失败,原因:" + e.getMessage());
		}
	}

	/** 采用正确的密码 */
	static void getDataByCorrectAuthentication() {
		String prefix = "[使用正确的授权信息]";
		try {
			System.out.println(prefix + "获取数据:" + PATH);
			
			System.out.println(prefix + "成功获取数据:" + zk.getData(PATH, false, null));
		} catch (Exception e) {
			System.out.println(prefix + "获取数据失败,原因:" + e.getMessage());
		}
	}

	/**
	 * 更新数据:不采用密码
	 */
	static void updateDataByNoAuthentication() {

		String prefix = "[不使用任何授权信息]";

		System.out.println(prefix + "更新数据: " + PATH);
		try {
			ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null);
			Thread.sleep(2000);
			Stat stat = nozk.exists(PATH, false);
			if (stat!=null) {
				nozk.setData(PATH, prefix.getBytes(), -1);
				System.out.println(prefix + "更新成功");
			}
		} catch (Exception e) {
			System.err.println(prefix + "更新失败,原因是:" + e.getMessage());
		}
	}

	/**
	 * 更新数据:采用错误的密码
	 */
	static void updateDataByBadAuthentication() {

		String prefix = "[使用错误的授权信息]";

		System.out.println(prefix + "更新数据:" + PATH);
		try {
			ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null);
			//授权
			badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());
			Thread.sleep(2000);
			Stat stat = badzk.exists(PATH, false);
			if (stat!=null) {
				badzk.setData(PATH, prefix.getBytes(), -1);
				System.out.println(prefix + "更新成功");
			}
		} catch (Exception e) {
			System.err.println(prefix + "更新失败,原因是:" + e.getMessage());
		}
	}

	/**
	 * 更新数据:采用正确的密码
	 */
	static void updateDataByCorrectAuthentication() {

		String prefix = "[使用正确的授权信息]";

		System.out.println(prefix + "更新数据:" + PATH);
		try {
			Stat stat = zk.exists(PATH, false);
			if (stat!=null) {
				zk.setData(PATH, prefix.getBytes(), -1);
				System.out.println(prefix + "更新成功");
			}
		} catch (Exception e) {
			System.err.println(prefix + "更新失败,原因是:" + e.getMessage());
		}
	}

	/**
	 * 不使用密码 删除节点
	 */
	static void deleteNodeByNoAuthentication() throws Exception {

		String prefix = "[不使用任何授权信息]";

		try {
			System.out.println(prefix + "删除节点:" + PATH_DEL);
			ZooKeeper nozk = new ZooKeeper(CONNECT_ADDR, 2000, null);
			Thread.sleep(2000);
			Stat stat = nozk.exists(PATH_DEL, false);
			if (stat!=null) {
				nozk.delete(PATH_DEL,-1);
				System.out.println(prefix + "删除成功");
			}
		} catch (Exception e) {
			System.err.println(prefix + "删除失败,原因是:" + e.getMessage());
		}
	}

	/**
	 * 采用错误的密码删除节点
	 */
	static void deleteNodeByBadAuthentication() throws Exception {

		String prefix = "[使用错误的授权信息]";

		try {
			System.out.println(prefix + "删除节点:" + PATH_DEL);
			ZooKeeper badzk = new ZooKeeper(CONNECT_ADDR, 2000, null);
			//授权
			badzk.addAuthInfo(authentication_type,badAuthentication.getBytes());
			Thread.sleep(2000);
			Stat stat = badzk.exists(PATH_DEL, false);
			if (stat!=null) {
				badzk.delete(PATH_DEL, -1);
				System.out.println(prefix + "删除成功");
			}
		} catch (Exception e) {
			System.err.println(prefix + "删除失败,原因是:" + e.getMessage());
		}
	}

	/**
	 * 使用正确的密码删除节点
	 */
	static void deleteNodeByCorrectAuthentication() throws Exception {

		String prefix = "[使用正确的授权信息]";

		try {
			System.out.println(prefix + "删除节点:" + PATH_DEL);
			Stat stat = zk.exists(PATH_DEL, false);
			if (stat!=null) {
				zk.delete(PATH_DEL, -1);
				System.out.println(prefix + "删除成功");
			}
		} catch (Exception e) {
			System.out.println(prefix + "删除失败,原因是:" + e.getMessage());
		}
	}

	/**
	 * 使用正确的密码删除节点
	 */
	static void deleteParent() throws Exception {
		try {
			Stat stat = zk.exists(PATH_DEL, false);
			if (stat == null) {
				zk.delete(PATH, -1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

四、应用场景实例

​ 当有多个客户端连接着zookeeper集群并且对zookeeper进行watch时,另外新增的客户端对zookeeper的操

​ 作可以通知到之前对zookeeper进行watch的客户端。详细代码在cluster包下面。

五、zkClient客户端

1、基础API

package com.lptxyl.zkClient;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.ZkConnection;

public class ZkClientBase {

	/** zookeeper地址 */
	static final String CONNECT_ADDR = "192.168.1.103:2181,192.168.1.104:2181,192.168.1.105:2181";
	/** session超时时间 */
	static final int SESSION_OUTTIME = 5000;//ms 
	
	
	public static void main(String[] args) throws Exception {
		ZkClient zkc = new ZkClient(new ZkConnection(CONNECT_ADDR), 50000);
		//1. create and delete方法 
		zkc.createEphemeral("/temp");
		zkc.createPersistent("/super/c1", true);
		Thread.sleep(10000);
//		zkc.delete("/temp");
//		zkc.deleteRecursive("/super");
		
		//2. 设置path和data 并且读取子节点和每个节点的内容
//		zkc.createPersistent("/super", "1234");
//		zkc.createPersistent("/super/c1", "c1内容");
//		zkc.createPersistent("/super/c2", "c2内容");
//		List<String> list = zkc.getChildren("/super");
//		for(String p : list){
//			System.out.println(p);
//			String rp = "/super/" + p;
//			String data = zkc.readData(rp);
//			System.out.println("节点为:" + rp + ",内容为: " + data);
//		}
		
		//3. 更新和判断节点是否存在
//		zkc.writeData("/super/c1", "新内容");
//		System.out.println(zkc.readData("/super/c1"));
//		System.out.println(zkc.exists("/super/c1"));
		
		//4.递归删除/super内容
//		zkc.deleteRecursive("/super");		
		zkc.close();
	}
}

2、watch模式

​ 代码1:

package com.lptxyl.zkClient.watcher;

import java.util.List;

import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.ZkConnection;

public class ZkClientWatcher1 {

	/** zookeeper地址 */
	static final String CONNECT_ADDR = "192.168.1.103:2181,192.168.1.104:2181,192.168.1.105:2181";
	/** session超时时间 */
	static final int SESSION_OUTTIME = 5000;//ms 
	
	
	public static void main(String[] args) throws Exception {
		ZkClient zkc = new ZkClient(new ZkConnection(CONNECT_ADDR), 50000);
		
		//对父节点添加监听子节点变化。
		zkc.subscribeChildChanges("/super", new IZkChildListener() {
			@Override
			public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
				System.out.println("parentPath: " + parentPath);
				System.out.println("currentChilds: " + currentChilds);
			}
		});
		
		Thread.sleep(3000);
		
		zkc.createPersistent("/super");
		Thread.sleep(1000);
		
		zkc.createPersistent("/super" + "/" + "c1", "c1内容");
		Thread.sleep(1000);
		
		zkc.createPersistent("/super" + "/" + "c2", "c2内容");
		Thread.sleep(1000);		
		
		zkc.delete("/super/c2");
		Thread.sleep(1000);	
		
		zkc.deleteRecursive("/super");
		Thread.sleep(Integer.MAX_VALUE);
		
		
	}
}

​ 代码2:

package com.lptxyl.zkClient.watcher;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.ZkConnection;

public class ZkClientWatcher2 {

	/** zookeeper地址 */
	static final String CONNECT_ADDR = "192.168.1.103:2181,192.168.1.104:2181,192.168.1.105:2181";
	/** session超时时间 */
	static final int SESSION_OUTTIME = 5000;//ms 
	
	
	public static void main(String[] args) throws Exception {
		ZkClient zkc = new ZkClient(new ZkConnection(CONNECT_ADDR), 5000);
		
		zkc.createPersistent("/super", "1234");
		
		//对父节点添加监听子节点变化。
		zkc.subscribeDataChanges("/super", new IZkDataListener() {
			@Override
			public void handleDataDeleted(String path) throws Exception {
				System.out.println("删除的节点为:" + path);
			}
			
			@Override
			public void handleDataChange(String path, Object data) throws Exception {
				System.out.println("变更的节点为:" + path + ", 变更内容为:" + data);
			}
		});
		
		Thread.sleep(3000);
		zkc.writeData("/super", "456", -1);
		Thread.sleep(1000);

		zkc.delete("/super");
		Thread.sleep(Integer.MAX_VALUE);
		
		
	}
}

六、Curator框架

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值