Zookeeper--開源客戶端Curator異步接口

Curator異步接口

Curator中引入了BackgroundCallback接口,用來處理異步接口調用之後服務端返回的結果信息,其接口定義如下。

public interface BackgroundCallback {
    void processResult(CuratorFramework client, CuratorEvent event) throws Exception;
}

Backg roundCallback接口只有一一個processResult方法,該方法會在操作完成後被異步調用。該方法的參數說明如下:
在這裏插入圖片描述

CuratorEvent定義了Zookeeper服務端發送到客戶端的一系列事件參數,其中比較重要的有事件類型和響應碼兩個參數:

事件類型(CuratorEventType):

getType()會返回事件的類型,主要有:

  • CREATE:對應方法CuratorFramework#create()
  • DELETE:對應方法CuratorFramework#delete()
  • EXISTS:對應方法CuratorFramework#checkExists()
  • GET_DATA:CuratorFramework#getData()
  • SET_DATA:CuratorFramework#setData()
  • CHILDREN:CuratorFramework#getChildren()
  • SYNC:CuratorFramework#sync(String,Object)
  • GET_ACL:CuratorFramework#getACL()
  • WATCHED:Watchable#usingWatcher(Watcher)Watchable#watched()
  • CLOSING:對應Zookeeper客戶端與服務度斷開連接事件

響應碼(int):
響應碼用於標識事件的結果狀態,所有響應碼都被定義在org . apache. zookeeper .KeeperException. Code類中

		OK(0),//成功
        SYSTEMERROR(-1),//服務端內部錯誤
        RUNTIMEINCONSISTENCY(-2),
        DATAINCONSISTENCY(-3),
        CONNECTIONLOSS(-4),//斷開連接
        MARSHALLINGERROR(-5),
        UNIMPLEMENTED(-6),
        OPERATIONTIMEOUT(-7),
        BADARGUMENTS(-8),
        APIERROR(-100),
        NONODE(-101),
        NOAUTH(-102),
        BADVERSION(-103),
        NOCHILDRENFOREPHEMERALS(-108),
        NODEEXISTS(-110),//指定節點已存在
        NOTEMPTY(-111),
        SESSIONEXPIRED(-112),//會話過期
        INVALIDCALLBACK(-113),
        INVALIDACL(-114),
        AUTHFAILED(-115),
        SESSIONMOVED(-118),
        NOTREADONLY(-119);

異步API:

Backgroundable<T>
	-- public T inBackground();
	-- public T inBackground(Object context);
	-- public T inBackground(BackgroundCallback callback);
	-- public T inBackground(BackgroundCallback callback, Object context);
	-- public T inBackground(BackgroundCallback callback, Executor executor);
	-- public T inBackground(BackgroundCallback callback, Object context, Executor executor);

在ZooKeeper中,所有異步通知事件處理都是由EventThread這個線程來處理的——EventThread 線程用於串行處理所有的事件通知。EventThread的“串行處理機制”在絕大部分應用場景下能夠保證對事件處理的順序性,但這個特性也有其弊端,就是一旦碰上一個複雜的處理單元,就會消耗過長的處理時間,從而影響對其他事件的處理。因此,在上面的inBackground接口中,允許用戶傳入一個Executor實例,這樣一來,就可以把那些比較複雜的事件處理放到一一個專門的線程池中去,如Executors. newFixedThreadPool( 2 )。

//使用Curator的異步接口
public class Create_Node_Background_Sample {

    static String path = "/zk-book";
    static CuratorFramework client = CuratorFrameworkFactory.builder()
            .connectString("127.0.0.1:2181")
            .sessionTimeoutMs(5000)
            .retryPolicy(new ExponentialBackoffRetry(1000, 3))
            .build();
    static CountDownLatch semaphore = new CountDownLatch(2);
    static ExecutorService tp = Executors.newFixedThreadPool(2);

    public static void main(String[] args) throws Exception {
        client.start();
        System.out.println("main thread: " + Thread.currentThread().getName());
        //此處傳入了自定的Executor
        client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL)
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        System.out.println("event[code: ]" + curatorEvent.getResultCode() + ", type: " + curatorEvent.getType() + "}");
                        System.out.println("Thread of processResult: " + Thread.currentThread().getName());
                        semaphore.countDown();
                    }
                }, tp).forPath(path, "init".getBytes());

        //此處沒有傳入自定義的Executor
        client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL)
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        System.out.println("event[code: ]" + curatorEvent.getResultCode() + ", type: " + curatorEvent.getType() + "}");
                        System.out.println("Thread of processResult: " + Thread.currentThread().getName());
                        semaphore.countDown();
                    }
                }).forPath(path, "init".getBytes());

        semaphore.await();
        tp.shutdown();
    }
}
main thread: main
event[code: ]-110, type: CREATE}
Thread of processResult: main-EventThread
event[code: ]0, type: CREATE}
Thread of processResult: pool-3-thread-1

上面這個程序使用了異步接口inBackground來創建節點,前後兩次調用,創建的節點名相同。從兩次返回的event中可以看出,第一次返回的響應碼是0,表明此次調用成功,即創建節點成功;而第二次返回的響應碼是-110,表明該節點已經存在,無法重複創建。這些響應碼和ZooKeeper原生的響應碼是一致的。

另外,我們再來看看前後兩次調用inBackground接口時傳入的Executor參數。第一次傳入了一個ExecutorService,這樣一來,Curator 的異步事件處理邏輯就會交由該線程池去做。而第二次調用時,沒有傳入任何Executor,因此會使用ZooKeeper默認的EventThread來處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章