ZooKeepe系列(2)--基於ZooKeeper實現簡單的配置中心

ZooKeeper節點的類型分爲如下幾類:程序員

  • 持久節點:節點建立後就一直存在,直到有刪除操做來主動刪除該節點json

  • 臨時節點:臨時節點的生命週期和建立該節點的客戶端會話綁定,即若是客戶端會話失效(客戶端宕機或下線),這個節點自動刪除bash

  • 時序節點:建立節點是能夠設置這個屬性,ZooKeeper會自動爲給定的節點加上一個數字後綴,做爲新的節點名。數字後綴的範圍是整型的最大值分佈式

  • 臨時性時序節點:同時具有臨時節點與時序節點的特性,主要用於分佈式鎖的實現工具

配置中心使用ZooKeeper的持久節點的特性,將配置信息寫入到持久節點。客戶端啓動時,從ZooKeeper讀取配置信息,進而初始化內部資源,達到配置統一管理的目的。再結合ZooKeeper的Watch特性,配置信息變化實時推送到客戶端,即時生效,無需重啓客戶端,達到配置熱更新的效果。ui

基於ZooKeeper實現簡易配置中心的示例以下:this

往服務端寫入配置,代碼以下:spa

public static void main(String[] strings){
        Map<String,String> env = new HashMap<String,String>();
        env.put("DB","222.111.188.187");
        env.put("SERVICE","222.111.188.188");
        env.put("REDIS","222.111.188.186");
        String json = JSON.toJSONString(env);
        new ConfigServer("localhost",2181).initConfig(json.getBytes());
    }

    private void initConfig(byte[] data) {
        ZooKeeper zooKeeper = null;
        try {
            zooKeeper = new ZooKeeper(this.ip + ":" + this.port,
                    30000, new Watcher() {
                // 監控全部被觸發的事件
                public void process(WatchedEvent event) {
                    System.out.println("已經觸發了" + event.getType() + "事件!" + event.getPath());
                }
            });
            //寫入配置
            Stat stat = zooKeeper.exists(EVN_PATH,false);
            if (stat != null){
                //獲取配置
                data = zooKeeper.getData(EVN_PATH,true,null);
                System.out.println("原有配置:" + new String(data));
                zooKeeper.setData(EVN_PATH,data,-1);
            }else{
                zooKeeper.create(EVN_PATH,data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
            System.out.println("寫入配置:" + new String(data));
        } catch (Exception e) {
            e.printStackTrace();
            if (zooKeeper != null){
                try {
                    zooKeeper.close();
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
複製代碼

客戶端從ZooKeeper查詢配置,代碼以下:code

public static void main(String[] strings){
        ConfigClient client = new ConfigClient("localhost",2181);
        byte[] config = client.getConfig();
        if (config == null || config.length < 1){
            System.out.println("獲取配置失敗");
        }
        String configStr = new String(config);
        System.out.println("配置爲:" + configStr);
        while(isRunning){
            try {
                synchronized (client) {
                    client.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }

    private byte[] getConfig() {
        ZooKeeper zooKeeper = null;
        byte[] data = null;
        try {

            zooKeeper = new ZooKeeper(this.ip  + ":" + this.port,
                    30000, new Watcher() {
                // 監控全部被觸發的事件
                // Watch 是一次性的,若是 watch 事件發生了,還想 watch 須要再設置新的watch
                public void process(WatchedEvent event) {
                    System.out.println("已經觸發了" + event.getType() + "事件!" + event.getPath()
                        + "," + event.getState());
                }
            });
            //獲取配置
            data = zooKeeper.getData(EVN_PATH,true,null);

        } catch (Exception e) {
            e.printStackTrace();
            if (zooKeeper != null){
                try {
                    zooKeeper.close();
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return data;
    }
複製代碼

以上就是簡單的配置中心實現樣例。可是還存在如下改進空間:cdn

1.沒有對數據變化進行監聽,須要在數據變化時實時獲取新的配置。(注:Zookeeper的API中的watch只能消費一次,需循環設置監聽)

2.能夠使用ZKClient或者Curator等ZooKeeper客戶端工具,解決了很是底層的細節開發工做,包括鏈接重連、反覆註冊Watcher和NodeExistsException異常等

若是各位有好的想法,歡迎關注個人公衆號(程序員順仔)留言討論~

相關文章
相關標籤/搜索