1. 程式人生 > >zookeeper模擬伺服器端啟動註冊,客戶端感知伺服器上下線

zookeeper模擬伺服器端啟動註冊,客戶端感知伺服器上下線

1.首先編寫伺服器端程式,原理就是上線一臺伺服器就會在/server這個組目錄下建立一個節點server,節點的值為臨時的(session消失後值也會消失)且為序列的(自動分配序列號),這樣伺服器上線下線,zookeeper的znode中的資料也會同步上建立和刪除。

伺服器端模擬程式碼如下:

package com.lijie.zk2;

import java.security.acl.Acl;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import
org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.ACL; public class MyServer { private static final String connectString = "hadoop01:2181,hadoop02:2181,hadoop03:2181"; private static final int sessionTimeout = 2000; private static ZooKeeper zk = null
; private static String group = "/server"; public static void main(String[] args) throws Exception { //註冊 regServer("192.168.80.123"); //執行任務 business("192.168.80.123"); } /** * 獲取zookeeper例項 * @return * @throws Exception */ public static
ZooKeeper getZookeeper() throws Exception { zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent event) { // 收到watch通知後的回撥函式 System.out.println("事件型別" + event.getType() + ",路徑" + event.getPath()); //因為監聽器只會監聽一次,這樣可以一直監聽,且只監聽"/"目錄 try { zk.getChildren("/", true); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); return zk; } /** * 註冊到zookeeper * @param ip * @throws Exception */ public static void regServer(String ip) throws Exception { zk = getZookeeper(); String create = zk.create(group + "/server", ip.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); System.out.println(ip + " 上線了!" + ",儲存路徑:" + create); } /** * 業務 * @throws Exception */ public static void business(String ip) throws Exception { System.out.println(ip + " 處理業務"); Thread.sleep(Long.MAX_VALUE); } }

2.然後編寫客戶端程式,原理就是執行對/server下面子節點的檢視並且監聽,其實就相當於ls /server watch,並且在process方法中再次呼叫getList方法更新列表並監聽,如果/server子節點有新增或者刪除,那麼這個監聽就會被觸發。

package com.lijie.zk2;

import java.util.ArrayList;
import java.util.List;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class MyClient {

    private static final String connectString = "hadoop01:2181,hadoop02:2181,hadoop03:2181";

    private static final int sessionTimeout = 2000;

    private static ZooKeeper zk = null;

    private static String group = "/server";

    private static volatile List<String> ipList = null;

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

        //獲取列表並且監聽
        getList();
        //執行業務
        business();
    }

    /**
     * 獲取zookeeper例項
     * @return
     * @throws Exception
     */
    public static ZooKeeper getZookeeper() throws Exception {
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                // 收到watch通知後的回撥函式
                System.out.println("事件型別" + event.getType() + ",路徑" + event.getPath());

                //重新更新列表,並註冊監聽
                try {
                    getList();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        return zk;
    }

    /**
     * 獲取伺服器列表,並監聽父節點下面的變化
     * @return
     * @throws Exception
     */
    public static void getList() throws Exception {
        zk = getZookeeper();
        //獲取節點名字
        List<String> children = zk.getChildren(group, true);
        //宣告裝載服務ip的集合
        ArrayList<String> ips = new ArrayList<String>();

        for (String path : children) {
            //獲取資料
            byte[] data = zk.getData(group + "/" + path, false, null);
            ips.add(new String(data));
        }
        ipList = ips;
        //列印伺服器列表
        System.out.println("列印伺服器列表" + ipList);
    }

    /**
     * 業務
     * @throws Exception
     */
    public static void business() throws Exception {
        System.out.println("客戶端處理");
        Thread.sleep(Long.MAX_VALUE);
    }

}

啟動兩個伺服器端,結果如圖

第一個:

這裡寫圖片描述

第二個:

這裡寫圖片描述

啟動客戶端:

這裡寫圖片描述

注意:上面的伺服器端執行沒有問題,但是客戶端執行的時候其實給我報錯了,但是當我debug的時候卻又沒問題(org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /server/server0000000002
),如下:
這裡寫圖片描述

網上查詢資料說是因為要先等zookeeper連線之後再執行後面的,可以使用CountDownLatch去控制,但是我這裡報這個錯之前會有這些ip顯示出來,應該不是這個問題,而且使用CountDownLatch去控制了依舊沒有效果,這個錯誤先放這,下次來解決。