操作zookeeper之原生API的基本操作

關鍵字: java原生API,創建連接,創建節點同步方式,獲取節點信息,獲取子節點信息,修改節點的值
,判斷節點是否存在,刪除節點,Zookeeper創建刪除等節點的異步方式
java慚怍zooleeper,一種是原生API,一種是zkclient方式,一種是curator框架操作
github: https://github.com/zhaikaishun/zookeeper_tutorial


java原生API

引入對應版本的jar包,例如我是3.4.5的zookeeper,那麼引入zookeeper-3.4.5.jar
簡要介紹一下原生API的簡單使用
連接zookeeper

ZooKeeper zk = new ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
  • connectString 連接服務器裂變,用逗號分開,例如192.168.1.31:2181,192.168.1.32:2181,192.168.1.33:2181,當然寫一個就可以了
  • sessionTimeout 心跳檢測時間週期(毫秒)
  • Watcher watcher,事件處理通知器
  • 這個其實有很多個構造方法,具體的,敲一下代碼看一下就一清二楚了
    比如下面這個例子吧

創建連接

public class ZookeeperBase {

    /** zookeeper地址 */
    static final String CONNECT_ADDR = "192.168.1.31:2181,192.168.1.32:2181,192.168.1.33:2181";
    /** session超時時間 */
    static final int SESSION_OUTTIME = 2000;//ms 
    /** 信號量,阻塞程序執行,用於等待zookeeper連接成功,發送成功信號 */
    static final CountDownLatch connectedSemaphore = new CountDownLatch(1);

    public static void main(String[] args) throws Exception{

        ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher(){
            @Override
            public void process(WatchedEvent event) {
                //獲取事件的狀態
                KeeperState keeperState = event.getState();
                EventType eventType = event.getType();
                //如果是建立連接
                if(KeeperState.SyncConnected == keeperState){
                    if(EventType.None == eventType){
                        //如果建立連接成功,則發送信號量,讓後續阻塞程序向下執行
                        System.out.println("zk 建立連接");
                        connectedSemaphore.countDown();
                    }
                }
            }
        });

        //進行阻塞
        connectedSemaphore.await();

        System.out.println("執行了");
    }
}
  1. new 了一個Zookeeper的實例,注意內部有一個new Watcher()方法,並且重寫了Watcher的process方法
  2. WatchedEvent.getState(),返回一個事件的狀態KeeperState,keeperState狀態有很多種:例如 SyncConnected(異步連接了)AuthFailed(認證失敗) ConnectedReadOnly(只讀連接)Disconnected(斷開連接)等
  3. EventType.getType返回一個節點事件,有 None(沒有任何操作) ,NodeCreated(節點創建) NodeDeleted(節點刪除),NodeDataChanged(節點數據改變),NodeChildrenChanged(子節點改變) 等等的事件
  4. 注意這裏用了一個CountDownLatch來進行線程之間通線,由於上面的客戶端和服務器端回話的建立是一個異步過程, 所以程序會往下執行,但是到了connectedSemaphore.await() 進行阻塞,直到connectedSemaphore.countDown();之後,阻塞被喚醒,才往下執行。
    當zookeeper集羣啓動後,運行代碼
zk 建立連接
執行了

創建節點同步方式

同步方式:
- 參數1,節點路徑(名稱):、nodeName (不允許遞歸創建節點,也就是說父節點不存在的情況下,不允許創建子節點)
- 參數2,節點內容:要求類型是字節數組(也就是說,不支持序列化方式,如果要實現序列化,可以用java相關序列化框架。如Kryo框架等)
- 參數3,節點權限,一般使用Ids.OPEN_ACL_UNSAFE權限即可。(這個參數一般在權限沒有太高要求的場景下使用)
- 參數4,節點類型:創建節點的類型:CreateMode.*。提供四種節點類型
PERSISTENT(持久節點), PERSISTENT_SEQUENTIAL(持久順序節點), EPHEMERAL(臨時節點), EPHEMERAL_SEQUENTIAL(臨時順序節點) 這幾種節點很重要,具體作用和案例,可以參考網上的。例如臨時節點一般只在本次session中有效,經常用來做分佈式鎖

創建父節點

        String result = zk.create("/testRoot", "testRoot".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println(result);
    --------輸出--------
    /testRoot

如果上面的目錄存在,再去創建就會報一下錯誤

KeeperException$NodeExistsException: KeeperErrorCode = NodeExists for /testRoot

創建子節點

        //創建子節點
        zk.create("/testRoot/children", "children data".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

如果子節點的父節點不存在,那麼會報 KeeperErrorCode = NoNode for /testRoot1/children 錯誤

獲取節點信息

        byte[] data = zk.getData("/testRoot", false, null);
        System.out.println(new String(data));

獲取子節點信息

獲取相對路徑

System.out.println(zk.getChildren("/testRoot", false));

通過相對路徑加上前面的路徑,然後可以一次獲取子節點的信息

修改節點的值

        zk.setData("/testRoot", "modify data root".getBytes(), -1);
        byte[] data = zk.getData("/testRoot", false, null);
        System.out.println(new String(data));

判斷節點是否存在

zk.exists("/testRoot/children", false)

刪除節點

zk.delete("/testRoot/children", -1);

Zookeeper創建刪除等節點的異步方式

在同步參數基礎上增加兩個參數
- 參數5,註冊一個異步回調函數,要實現AsynCallBack.StringCallBack接口,重寫processResult(int rc,String path,Object ctx,String name)方法,當節點創建完畢後執行此方法。
rc: 爲服務端響應代碼0表示調用成功、-4表示端口連接、-110表示指定節點存在、-112表示回話已經過期。
path:接口調用時傳入API的數據節點的路徑參數。
ctx:爲調用接口傳入API的ctx值。
name:實際在服務器端創建節點的名稱。
- 參數6,傳遞給回調函數的參數,一般爲上下文(Context)信息
舉例:

        zk.delete("/node01", -1, new AsyncCallback.VoidCallback() {
            @Override
            public void processResult(int rc, String path, Object ctx) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("rc: "+rc);
                System.out.println("path: "+path);
                System.out.println("ctx: "+ctx);
            }
        },"a");
        System.out.println("繼續執行");
        Thread.sleep(5000);

輸出

繼續執行
rc: 0
path: /node01
ctx: a

特別感謝互聯網架構師白鶴翔老師,本文大多出自他的視頻講解。
筆者主要是記錄筆記,以便之後翻閱,正所謂好記性不如爛筆頭,爛筆頭不如雲筆記

發佈了137 篇原創文章 · 獲贊 211 · 訪問量 59萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章