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異常等
若是各位有好的想法,歡迎關注個人公衆號(程序員順仔)留言討論~