ZooKeeper非同步調用命令
- 2019 年 10 月 3 日
- 筆記
在ZooKeeper中,所有的同步調用命令,都會有一個相應的非同步調用方法。非同步調用能在一個單獨執行緒中同時提交更多的命令,也能在一定程度上簡化程式碼實現。
1 非同步create方法
如創建zNode的命令create,同步方法的定義是
/** * @param path 創建節點的路徑 * @param data 創建節點的初始值 * @param acl 創建節點的ACL * @param createMode 創建節點使用永久還是臨時模式 * @return 創建節點的真實路徑 * @throws KeeperException 伺服器返回了非0的錯誤程式碼 * @throws KeeperException.InvalidACLException ACL非法或者為空 * @throws InterruptedException 事務被中斷 * @throws IllegalArgumentException 路徑非法 */ public String create(final String path, byte data[], List<ACL> acl, CreateMode createMode);
對應的非同步調用方法
/** * create方法的非同步調用方法 * @param path 創建節點的路徑 * @param data 創建節點的初始值 * @param acl 創建節點的ACL * @param createMode 創建節點使用永久還是臨時模式 * @param cb 包括回調函數的對象 * @param ctx 上下文對象(非同步回調時會傳遞給callback,方便出錯時重新調用) */ public void create(final String path, byte data[], List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx);
StringCallback的定義
interface StringCallback extends AsyncCallback { /** * 處理非同步調用的結果 * @param rc 調用的返回碼 * @param path 非同步調用時的路徑參數 * @param ctx 非同步調用時的上下文對象 * @param name 實際創建的節點名 * 成功時通常同path相同,除非創建的是sequential節點 */ public void processResult(int rc, String path, Object ctx, String name); }
非同步調用與同步調用的兩個主要區別:
- 非同步調用沒有返回值(void)
- 非同步調用不拋出異常,異常情況都通過rc參數傳遞
2 部分rc程式碼定義
回調函數的第一個參數 rc ,是調用的返回值。ZooKeeper在枚舉org.apache.zookeeper.KeeperException.Code中做了定義。從源碼中摘出一些我們可能會經常使用的Code
/** 一切安好 */ OK (Ok), /** 伺服器連接丟失 */ CONNECTIONLOSS (ConnectionLoss), /** 操作超時 */ OPERATIONTIMEOUT (OperationTimeout), /** 參數錯誤 */ BADARGUMENTS (BadArguments), /** 節點不存在 */ NONODE (NoNode), /** 臨時節點沒有子節點 */ NOCHILDRENFOREPHEMERALS (NoChildrenForEphemerals), /** 節點已經存在 */ NODEEXISTS (NodeExists), /** 節點有子節點 */ NOTEMPTY (NotEmpty), /** 會話超時 */ SESSIONEXPIRED (SessionExpired), /** 請求超時*/ REQUESTTIMEOUT (-122),
3 回調函數的一般用法
下面是一個創建節點的簡單例子。注意,ctx參數傳遞的是data,這個參數會直接傳遞到callback函數中,這樣就可以直接重新調用create命令。
void createNode(String path, byte[] data) { zooKeeper.create(nodePath, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, nodeCreateCallback, data); } AsyncCallback.StringCallback nodeCreateCallback = new AsyncCallback.StringCallback() { public void processResult(int rc, String path, Object ctx, String name) { switch (KeeperException.Code.get(rc)) { case OK: // 創建節點成功 break; case CONNECTIONLOSS: // 連接丟失,重新發布命令 createNode(path, ctx); return; default: // 其他異常,拋出或記錄異常 KeeperException e = KeeperException.create(KeeperException.Code.get(rc), path); log.error("create node error", e); } } };
4 非同步回調介面定義
ZooKeeper在org.apache.zookeeper.AsyncCallback中定義了幾個回調介面
回調介面 |
說明 |
適用的非同步命令 |
StatCallback |
用於獲取節點的狀態 |
void exists() void setData() |
DataCallback |
用於獲取節點的值和狀態 |
void getData() void getConfig() |
ACLCallback |
用於獲取節點的ACL資訊和狀態 |
void getACL() |
ChildrenCallback |
用於獲取節點的子節點列表 |
void getChildren() |
Children2Callback |
用於獲取節點的子節點列表和狀態 |
void getChildren() |
Create2Callback |
用於獲取節點的名稱和狀態 |
void create() |
StringCallback |
用於獲取節點的名稱 |
void create() |
VoidCallback |
不返回任何資訊 |
void delete() void sync() void removeWatches() void removeAllWatches() |
MultiCallback |
用於多命令請求的返回值 |
void multi() |
可以看到,有些非同步命令,可以選擇使用多個不同的Callback,見下表
非同步命令 |
可選的回調介面 |
介面說明 |
void create() |
Create2Callback |
用於獲取節點的名稱和狀態 |
StringCallback |
用於獲取節點的名稱 |
|
void getChildren() |
ChildrenCallback |
用於獲取節點的子節點列表 |
Children2Callback |
用於獲取節點的子節點列表和狀態 |