首页 > 代码库 > ZooKeeper实践:(2)集群管理

ZooKeeper实践:(2)集群管理

前言:

       随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机器故障及时移除集群,添加机器了如何及时的感应到,Zookeeper不仅能维护当前的集群服务状态,还能及时的选出master,它们的实现方式都是在Zookeeper上面注册一个EPHEMERAL目录节点,在创建目录的父目录上面调用getChildren(String path,boolean watch)设置watch为true,注册watcher事件,由于是临时节点,当服务器出现问题造成session丢失,相对应的目录节点随之删除,Children节点发生变化,就会调用前面注册的watcher,使集群内的每个节点都得到新的集群信息。反之,新增节点也是这样。

注:master选举,不同之处是注册一个EPHEMERAL_SEQUENTIAL 目录节点,我们可以选择最小编号为master,实现了动态选择master,避免master出现单点故障

一、架构体系

      技术分享

二:模拟代码

      监控类: 

package com.zk.config.manager;import java.io.IOException;import java.util.Collections;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.ZooKeeper;import org.apache.zookeeper.Watcher.Event.EventType;import org.apache.zookeeper.Watcher.Event.KeeperState;import org.apache.zookeeper.ZooDefs.Ids;public class AppRegister {	private CountDownLatch connectedSemaphore = new CountDownLatch(1);	private ZooKeeper zooKeeper;	private Object lock = new Object();	private String ip;	private String rootConfig;	public AppRegister(String ip, String root) {		this.ip = ip;		this.rootConfig = root;		this.zooKeeper = connectZookeeper();	}	public ZooKeeper connectZookeeper() {		synchronized (lock) {			if (zooKeeper == null) {				try {					zooKeeper = new ZooKeeper("10.32.180.251:2181", 5000, new Watcher() {						public void process(WatchedEvent event) {							if (KeeperState.SyncConnected == event.getState()) {								if (EventType.None == event.getType() && null == event.getPath()) {									try {										connectedSemaphore.countDown();										zooKeeper.getChildren(rootConfig, true);										zooKeeper.create(rootConfig + "/" + ip, ip.getBytes(), Ids.OPEN_ACL_UNSAFE,												CreateMode.EPHEMERAL_SEQUENTIAL);									} catch (KeeperException e) {										e.printStackTrace();									} catch (InterruptedException e) {										e.printStackTrace();									}								} else if (EventType.NodeChildrenChanged == event.getType()) {									try {										List<String> childrenList = zooKeeper.getChildren(rootConfig, true);										System.out.println("节点变化了:" + childrenList);										Collections.sort(childrenList);										System.out.println("我是master了:" + childrenList.get(0));									} catch (KeeperException e) {										e.printStackTrace();									} catch (InterruptedException e) {										e.printStackTrace();									}								}							}						}					}					);					connectedSemaphore.await();				} catch (IOException e) {					e.printStackTrace();				} catch (InterruptedException e) {					e.printStackTrace();				}			}		}		return zooKeeper;	}}

 模拟程序:

package com.zk.config.manager;public class AppMonitor {	private final static String rootConfig = "/AppCluster";	public static void main(String[] args) throws InterruptedException {				/**		 * 新增机器,选举master		 */		addHost();				Thread.sleep(Integer.MAX_VALUE);	}		private static void  addHost()	{		new Thread(new Runnable() {			public void run() {				new AppRegister("192.168.1.1", rootConfig);			}		}).start();		new Thread(new Runnable() {			public void run() {				try {					Thread.sleep(2000);					new AppRegister("192.168.1.2", rootConfig);				} catch (InterruptedException e) {					// TODO Auto-generated catch block					e.printStackTrace();				}			}		}).start();		}}

 运行结果:

节点变化了:[192.168.1.10000000029]
我是master了:192.168.1.10000000029
节点变化了:[192.168.1.20000000030, 192.168.1.10000000029]
我是master了:192.168.1.10000000029
节点变化了:[192.168.1.20000000030, 192.168.1.10000000029]
我是master了:192.168.1.10000000029

ZooKeeper实践:(2)集群管理