zookeeper主备切换学习
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了zookeeper主备切换学习相关的知识,希望对你有一定的参考价值。
今天了解了下Zookeeper的主备方案
大致就是两个应用运行后同时抢一个临时节点,zookeeper可以保证只会有一个注册成功这个节点,
然后都对这个节点进行watch,监听事件NodeDeleted,如果NodeDeleted,然后另一台就可以直接注册临时节点成功。
这样可以保证主备自动切换。看起来还可以...没有在产线上用过...所以不知道具体效果是什么样的。
实现代码如下:非常easy。。。。
//抄的, public class AbstractZooKeeper implements Watcher { private static final int Session_TIME =2000; protected ZooKeeper zookeeper ; /*一个同步辅助类,在完成一组正在其他线程中执行的操作之前, 它允许一个或多个线程一直等待。 用给定的计数 初始化 CountDownLatch。 由于调用了 countDown() 方法, 所以在当前计数到达零之前,await 方法会一直受阻塞。 之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。 这种现象只出现一次——计数无法被重置 */ protected CountDownLatch countDownLatch = new CountDownLatch(1); public void connect(String hosts) throws IOException,InterruptedException{ zookeeper= new ZooKeeper(hosts,Session_TIME,this); countDownLatch.await(); } //监听 public void process(WatchedEvent event) { /* 一旦客户端和服务器的某一个节点建立连接 * (注意,虽然集群有多个节点, * 但是客户端一次连接到一个节点就行了), * 并完成一次version、zxid的同步, * 这时的客户端和服务器的连接状态就是SyncConnected*/ if(event.getState() == KeeperState.SyncConnected){ countDownLatch.countDown(); System.out.println(countDownLatch.getCount()); } } public void close() throws InterruptedException{ zookeeper.close(); } }
///zookeeper的一些操作。和监听zookeeper临时节点删除事件。 public class ZookeeperService extends AbstractZooKeeper { private static final String host = "helloword1"; //private static final String host = "helloword2"; private static final String rootNode="/mynode"; public void Create() throws KeeperException, InterruptedException, UnsupportedEncodingException { //EPHEMERAL :临时节点 this.zookeeper.create(rootNode, host.getBytes("utf-8"), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); } //判断存不存在时开始监听 public Boolean Exist() throws KeeperException, InterruptedException { return (this.zookeeper.exists(rootNode, true) != null); } //监听事件 @Override public void process(WatchedEvent event){ if(event.getType() == EventType.NodeDeleted){ try { this.Create(); System.out.println(host); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(host); } else{ //由于第一次是阻塞的, //如果连接成功需要调用父类的将countDownLatch阻塞去掉 super.process(event); } } public Boolean getChild(String path) throws KeeperException, InstantiationException { Boolean res = false; try { List<String> list = this.zookeeper.getChildren(path, false); if (list.isEmpty()) { System.out.println(path + "没有节点"); } else { res = true; System.out.println("节点列表"); for (String child : list) { System.out.println(child); } } } catch (Exception e) { // e.printStackTrace(); } return res; } public byte[] getData(String path) throws KeeperException, InterruptedException { return this.zookeeper.getData(path, false, null); } public static void main(String[] args) { try { ZookeeperService zookeeperService = new ZookeeperService(); zookeeperService.connect("localhost"); String zktest = "Zookeeper的JAVA API 测试"; zookeeperService.Create(); zookeeperService.getChild("/"); // zookeeperService.close(); } catch (Exception e) { e.printStackTrace(); } } }
//启动方法, public static void main(String[] args) { SetZookeeperInfo(); SpringApplication.run(Application.class, args); } public static void SetZookeeperInfo() { ZookeeperService zookeeperService = new ZookeeperService(); try { zookeeperService.connect("localhost"); if(!zookeeperService.Exist()) { zookeeperService.Create(); } zookeeperService.getChild("/"); } catch (Exception e) { e.printStackTrace(); } }
两个应用代码完全一样,但只有节点对应的值不一样,当一台机器挂机后,可查看zookeeper 上的节点的值 变成了另外一个,
以上是关于zookeeper主备切换学习的主要内容,如果未能解决你的问题,请参考以下文章