天天看點

zookeeper快速入門五:用zookeeper實作服務注冊與發現中心

經過前面四章的講解,我們已經對zookeeper建立起初步的概念,這篇文章就來做一個小小的實踐,用zookeeper實作一個簡單版的服務注冊與發現中心。

zookeeper的一個常見功能就是作為服務注冊與發現中心。

我們先建立一個節點/services。

Stat stat = zkClient.exists("/services",false);
        if (stat == null ){
            zkClient.create("/services","".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
           

每當有一個服務上線時,我們就向我們的服務注冊與發現中心zookeeper注冊我們的應用。

比如,我們注冊一個user服務,服務位址是localhost:8080,那麼我們就在/services下面建立一個user子節點,子節點資料為user服務的真實url位址,比如localhost:8080,子節點類型為臨時節點。

public void registerService()throws Exception{
        zkClient.create("/services/user","localhost:8080".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);

    }
           

當我們向user請求服務時,首先通過/services節點擷取user服務,判斷user服務是否存在。進而擷取它的位址,發起真正的請求。同時,我們注冊一個監聽事件,監聽節點的狀态變化。當user服務出現故障或其他因素而下線時,/services/user節點會被删除,zookeeper server會通知到監聽這個節點的用戶端,進而使用戶端做出自己的響應,同樣的,當user服務上線或位址修改,用戶端也能收到通知。

public void invokeUserService()throws Exception{
        Stat stat = zkClient.exists("/services/user",false);
        if (stat == null){
            System.out.println("未能找到user服務,服務未注冊或已下線");
        }
        byte[] url = zkClient.getData("/services/user", new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                if (watchedEvent.getType() == Event.EventType.NodeDeleted){
                    System.out.println("服務下線");
//                    處理業務邏輯
                }
                if (watchedEvent.getType() == Event.EventType.NodeCreated){
                    System.out.println("服務上線");
//                    處理業務邏輯
                }
                if (watchedEvent.getType() == Event.EventType.NodeDataChanged){
                    System.out.println("服務位址修改了");
                }
            }
        }, null);
//        處理業務邏輯
         System.out.println("向"+new String(url)+"發起請求");
    }
           
zookeeper快速入門五:用zookeeper實作服務注冊與發現中心

如果對前面有印象的話,應該記得zookeeper的watcher隻觸發一次,當節點狀态改變一次之後,節點狀态的第二次改變就不能監聽到了。為了能夠持續監聽,我們需要修改一下我們的代碼。

我們把判斷服務上線的代碼挪到上面來,并且在下面的監聽事件裡回調invokeUserService方法,實作持續監聽的功能。

為了簡單易懂,這裡代碼寫得并不夠好,如果是實際項目,需要再做點拆分與封裝。

public void invokeUserService()throws Exception{
        Stat stat = zkClient.exists("/services/user",false);
        if (stat == null){
            System.out.println("未能找到user服務,服務未注冊或已下線");
            zkClient.exists("/services/user", new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {
                    if (watchedEvent.getType() == Event.EventType.NodeCreated){
                        System.out.println("服務上線");
//                    處理業務邏輯
                    }
                }
            });
        }else{
            byte[] url = zkClient.getData("/services/user", new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {
                    if (watchedEvent.getType() == Event.EventType.NodeDeleted){
                        System.out.println("服務下線");
//                    處理業務邏輯
                    }
                    if (watchedEvent.getType() == Event.EventType.NodeDataChanged){
                        System.out.println("服務位址修改了");
                    }
                    try {
                        invokeUserService();
                    }catch (Exception e){

                    }
                }
            }, null);
//        處理業務邏輯
            System.out.println("向"+new String(url)+"發起請求");
        }

    }
           
zookeeper快速入門五:用zookeeper實作服務注冊與發現中心

zookeeper作為一個分布式協調架構,它的建立就是為了友善或者簡化分布式應用的開發。除了服務注冊與發現之外,它還能夠提供更多的功能,但是對于入門來說,簡單的了解到這裡就已經足夠了。下面會講zookeeper的架構設計與原理,比如zookeeper的原子協定,leader選舉算法等。