前段時間項目中用到Zookeeper,前人已經搭建好環境、封裝好業務邏輯、只須要配置一下就能夠用。簡單但不夠深刻,有點‘紙上得來終覺淺,絕知此事要躬行’的感受。 Zookeeper環境很是容易搭建,只須要注意下配置文件,在myid文件中寫上配置文件中的編號便可,參考:http://attend.iteye.com/blog/1454212 查看ZK源代碼,發現網絡通訊用的是NIO實現的,創建客戶端鏈接時,必定要等到狀態爲已鏈接時才能夠進行下一步操做,代碼實現藉助鎖的邏輯來實現。如: final CountDownLatch countDownLatch = new CountDownLatch(1); ZK 很大的用處是ZK集羣上的每個變化均可以通知到自定義的Watchcer實現。利用ZK集羣的高可用性(2X+1臺機器,容忍X臺機器掛掉)。而且ZK有一套如文件系統通常的能夠增刪改查的數據模型(Znode)。運用這套模型來實現自定義服務。有點抽象,畫個圖,以下:
客戶端鏈接到ZK的物理集羣中,集羣中維護了Znode模型,客戶端對znode進行操做,由Zk維護Znode模型的一致性和高可用性,而且能夠對Znode節點增刪改查數據。也能夠用給Znode模型上添加新的節點。添加節點若是須要監控這個節點須要調用 zooKeeper.exists(path, true);方法,這個方法做用是:若是存在path並設置watch爲true,監控起來,這樣就能夠把針對這個path的變化 通知到watcher.(明白這點很是重要,初學者常犯並無watcher這個path,就想獲取到針對這個path的事件)。 來段測試代碼: package com.jcloud.zk.taokepper.reader; import java.io.IOException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; 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.KeeperState; import org.apache.zookeeper.ZooDefs.Ids; public class ZkReader { public static void main(String args[]) throws IOException, KeeperException, InterruptedException { //藉助於該方法實現剛開始鏈接等待,鏈接好後,才容許下一步的邏輯。 final CountDownLatch countDownLatch = new CountDownLatch(1); final ZooKeeper zooKeeper = new ZooKeeper("10.28.174.199:2181;10.28.174.79:2181", 10000, new Watcher() { @Override public void process(WatchedEvent event) { System.out.println("event." +event); if (null != event) { if (event.getState() == KeeperState.SyncConnected) { //若是鏈接好了,能夠下一步操做 countDownLatch.countDown(); System.out.println("---> created..."); } } } }); countDownLatch.await(); //等到鏈接完成後後,開始下一步。 System.out.println("--->"); AtomicInteger increInt = new AtomicInteger(); String path="/2testnode0"; while (true) { Thread.sleep(1000L); //zooKeeper.create(path, "ttttt".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); //要在這個Path上作watcher zooKeeper.exists(path, true); //修改節點數據,觸發watcher zooKeeper.setData(path, (path+increInt.getAndAdd(1)).getBytes(), -1); zooKeeper.setData(path, (path+increInt.getAndAdd(1)).getBytes(), -1); System.out.println((path+increInt.getAndAdd(1))); } } } Zk有些經典使用場景,好比配置項推送,作法是,多個客戶端鏈接到ZK集羣中,監控同一個Znode,只要一個客戶端改變了這個Znode,其餘監控的客戶端均可以收到相應的消息。 還能夠用來作服務高可用性,最經典的用法是服務器起來的話,建立一個臨時Znode,服務掛掉後刪除這個Znode,其餘監控到這個Znode的客戶端也能夠收到服務是否可用的消息。 還能夠用來作選舉場景,多個客戶端建立同一個Znode,誰建立成功了誰就是老大。關於這個Znode的一致性就讓ZK集羣完成吧。 整體感受ZK確實提供是一款不錯的一致性、高可用性工具。試着去用好它。