關鍵字: 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("執行了");
}
}
- new 了一個Zookeeper的實例,注意內部有一個new Watcher()方法,並且重寫了Watcher的process方法
- WatchedEvent.getState(),返回一個事件的狀態KeeperState,keeperState狀態有很多種:例如 SyncConnected(異步連接了)AuthFailed(認證失敗) ConnectedReadOnly(只讀連接)Disconnected(斷開連接)等
- EventType.getType返回一個節點事件,有 None(沒有任何操作) ,NodeCreated(節點創建) NodeDeleted(節點刪除),NodeDataChanged(節點數據改變),NodeChildrenChanged(子節點改變) 等等的事件
- 注意這裏用了一個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
特別感謝互聯網架構師白鶴翔老師,本文大多出自他的視頻講解。
筆者主要是記錄筆記,以便之後翻閱,正所謂好記性不如爛筆頭,爛筆頭不如雲筆記