在Zookeeper的主要應用場景中,其中之一是作為分布式系統的配置中心。
實現原理
在Zookeeper建立一個根節點,比如/CONFIG,代表某個配置文件。將配置文件中的信息作為根節點的子節點存儲,比如配置項timeout=3000,在Zookeeper中展現為:/CONFIG/timeout ,節點內容是3000。然后讓所有使用到該配置信息的應用機器集成Zookeeper並監控/CONFIG的狀態,一旦配置信息也就是子節點發生變化,每台應用機器就會收到ZK的通知,然后從ZK中獲取新的配置信息應用到系統中。
以下代碼僅用於展現實現思路,具體生產還需要根據實際場景處理和優化
我們使用Curator來實現一個簡易的配置中心,關於Curator框架的使用可參考zookeeper客戶端框架Curator
項目中引入依賴包:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.0.1</version>
</dependency>
Config.java 配置類
public class Config {
private Map<String, String> cache = new HashMap<>();
private CuratorFramework client;
private static final String CONFIG_PREFIX = "/CONFIG";
// 初始化zk連接
public Config() {
this.client = CuratorFrameworkFactory.newClient("localhost:2181", new RetryNTimes(3, 1000));
this.client.start();
this.init();
}
public void init() {
try {
// 從zk中獲取配置項並保存到緩存中
List<String> childrenNames = client.getChildren().forPath(CONFIG_PREFIX);
for (String name : childrenNames) {
String value = new String(client.getData().forPath(CONFIG_PREFIX + "/" + name));
cache.put(name, value);
}
// 綁定一個監聽器 cacheData設為true,事件發生后可以拿到節點發送的內容。
// 使用該配置文件的每個應用機器都需要監聽,這里只是用於演示
PathChildrenCache watcher = new PathChildrenCache(client, CONFIG_PREFIX, true);
watcher.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event) throws Exception {
String path = event.getData().getPath();
if (path.startsWith(CONFIG_PREFIX)) {
String key = path.replace(CONFIG_PREFIX + "/", "");
// 子節點新增或變更時 更新緩存信息
if (PathChildrenCacheEvent.Type.CHILD_ADDED.equals(event.getType()) ||
PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(event.getType())) {
cache.put(key, new String(event.getData().getData()));
}
// 子節點被刪除時 從緩存中刪除
if (PathChildrenCacheEvent.Type.CHILD_REMOVED.equals(event.getType())) {
cache.remove(key);
}
}
}
});
watcher.start();
} catch (Exception e) {
e.printStackTrace();
}
}
// 保存配置信息
public void save(String name, String value) {
String configFullName = CONFIG_PREFIX + "/" + name;
try {
Stat stat = client.checkExists().forPath(configFullName);
if (stat == null) {
client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(configFullName, value.getBytes());
} else {
client.setData().forPath(configFullName, value.getBytes());
}
cache.put(name, value);
} catch (Exception e) {
e.printStackTrace();
}
}
// 獲取配置信息
public String get(String name) {
return cache.get(name);
}
}
Test.java 測試類
public class Main {
public static void main(String[] args) {
Config config = new Config();
// 模擬一個配置項,實際生產中會在系統初始化時從配置文件中加載進來
config.save("timeout", "1000");
// 每3S打印一次獲取到的配置項
for (int i = 0; i < 10; i++) {
System.out.println(config.get("timeout"));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
啟動本地zookeeper服務器,我們來測試下。Main.java執行后會在控制台每隔3S打印一下當前獲取到的配置信息,當我們使用其它zk客戶端重新設置timeout值時會發現獲取到的信息及時更新了。
至此,我們使用Zookeeper實現了一個簡單的共享配置中心。
————————————————
版權聲明:本文為CSDN博主「岸遠水聲微」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/hzygcs/article/details/88387408