Zookeeper学习:Zookeeper的Watcher机制

Watch:
vt.
注视,注意;看守,监视;守候(机会等);密切注意
n.
表;值夜,值班;看守,监视;值班人员
vi.
观看;注视;守候;看守

Zookeeper的watch时间是一次性触发的,当watch监视的数据发生变化时,将信息通知给设置了该watch的client端,即watcher。所以,当watcher监视的数据发生了变化,那就有其对应的事件类型和状态类型。

事件类型(与Znode节点相关的):
    	        EventType.NodeCreated   							//创建节点事件
		EventType.NodeDataChanged					        //节点数据产生变化
		EventType.NodeChildrenChanged			            //节点的子节点产生变化
		EventType.NodeDeleted							    //删除节点事件
状态类型(与客户端示例相关的):
            KeeperState.Disconnected							//连接失败
	    KeeperState.SyncConnected							//连接成功
	    KeeperState.AuthFailed								//认证失败
	    KeeperState.Expired									//认证过期

举个栗子:创建一个节点,此时应该有事件类型:NodeCreated,但这些应该是基于状态类型:SyncConnected,代码示例如下:

main:
		//创建连接
    	zkWatcher.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);
    	try {
			Thread.sleep(1*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    	//创建节点
    	if(zkWatcher.createPath(NODE_CHILDREN, System.currentTimeMillis()+"", true)) {
    		System.out.println();
    	}
    	while(true) {
    		
    	}

createConnection:
    //创建连接
	public ZooKeeper createConnection(String connectAddr,int sessionTimeout) {
		this.releaseConnection();
		try {
			zk = new ZooKeeper(connectAddr,sessionTimeout,this) ;
			System.out.println("【Main】"+"开始连接ZooKeeper服务器");
			//connectedSemaphore.wait();
		} catch (IOException e) {
			e.printStackTrace();
		//} catch (InterruptedException e) {
		//	e.printStackTrace();
		}
		return zk;
	}

createZnode:
    //创建节点
		//设置监控(由于watch都是一次性的,所以每次都需要设置监控)
		try {
			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;
	

上面代码中创建连接是所需要的“this”就是一个自定义的watcher,重写watcher的process方法,如下:

	public void process(WatchedEvent event) {
		System.out.println("进入process,Event is "+event);
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if(event == null) {
			return ;
		}
		
		//连接状态
		KeeperState keeperState = event.getState();
		//事件类型
		EventType eventType = event.getType();
		//受影响的节点路径
		String path = event.getPath();
		//原子对象seq,记录进入process的次数
		String logPrefix = "【Watcher - "+this.seq.incrementAndGet()+"】";
		
		System.out.println(logPrefix + "收到Watcher通知");
		System.out.println(logPrefix + "连接状态:"+keeperState.toString());
		System.out.println(logPrefix + "事件类型:"+eventType.toString());
		System.out.println(logPrefix + "受影响的节点路径:"+path);
		
		/*
		 * Watcher四个状态:Disconnected、SyncConnected、AuthFailed、Expired
		 */
		//连接Zookeeper服务器
		if(KeeperState.SyncConnected == keeperState) {
			/*
			 * Watcher四个事件类型:NodeCreated、NodeDataChanged、NodeChildrenChanged、NodeDeleted
			 */
			//成功连接上ZK服务器,刚连接上Zookeeper服务器,所以事件类型为None
			if(EventType.None == eventType) {
				System.out.println(logPrefix + "成功连接上zk服务器");
				//connectedSemaphore.countDown();
			}
			//创建节点
			else if(EventType.NodeCreated == eventType) {
				System.out.println(logPrefix+"创建节点");
				try {
					Thread.sleep(3*1000);
				} catch (InterruptedException e) {
					System.out.println(e.getMessage());
				}
			}
			//更新节点数据
			else if(EventType.NodeDataChanged == eventType) {
				System.out.println(logPrefix+"更新节点数据信息");
				try {
					Thread.sleep(3*1000);
				} catch (InterruptedException e) {
					System.out.println(e.getMessage());
				}
			}
			//更新节点的子节点
			else if(EventType.NodeChildrenChanged == eventType) {
				System.out.println(logPrefix+"更新节点的子节点");
				try {
					Thread.sleep(3*1000);
				} catch (InterruptedException e) {
					System.out.println(e.getMessage());
				}				
			}
			//删除节点
			else if(EventType.NodeDeleted == eventType) {
				System.out.println(logPrefix+"删除节点");
				try {
					Thread.sleep(3*1000);
				} catch (InterruptedException e) {
					System.out.println(e.getMessage());
				}				
			}
			//没了
			else {
				System.out.println("Hello World");
			}
		}
		//断开Zookeeper服务器
		else if(KeeperState.Disconnected == keeperState) {
			System.out.println(logPrefix+"断开Zookeeper服务器");
		}
		//连接认证失败
		else if(KeeperState.AuthFailed == keeperState) {
			System.out.println(logPrefix+"连接认证失败");
		}
		//连接认证过期
		else if(KeeperState.Expired == keeperState) {
			System.out.println(logPrefix+"连接认证过期");
		}
		//没了
		else {
			System.out.println("Hello World");
		}
	}

控制台打印创建节点信息:

Zookeeper服务器上对应节点创建成功:

备注:

        1、将exists(String path, boolean watch) 的watch参数设置为false时,对于接下来的创建节点将不会被watch监控,控制台打印效果如下:

        2、exists方法重载:exists(String path, Watcher watcher) ,即实例化一个新的watch来监听接下来对Zookeeper服务器的操作,只是此方式可以根据不同的场景灵活指定具体的watcher对象而不是使用原来的watcher。

猜你喜欢

转载自blog.csdn.net/txd2016_5_11/article/details/86152265