zookeeper主備切換學習
阿新 • • 發佈:2017-11-11
sem ant gen pri print 建立 mode reat 調用
今天了解了下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主備切換學習