市面上的配置中心產品
說到配置中心,大家應該也瞭解目前市面上用的較多的配置中心:
百度的Disconf、Spring Cloud Config、攜程的Apollo、阿里的Nacos等。
由於Disconf不再維護,以下對Spring Cloud Config、Apollo、Nacos的功能點做的對比
大家平時在開發時,項目中會用到很多配置,有些配置還和環境有關,開發、測試和生產的配置也不一樣;
或者在做某一個功能時,上線後配置有可能更改,即使我們將變量寫在配置中,但還是需要重新發布服務,
所以,如果有個配置中心,當更新某個配置時,可以實時生效,豈不快哉!
如果做一個分佈式配置中心的產品,所需要實現的功能很多,如配置存儲、配置實時推送、權限校驗、版本管理&回滾、配置格式校驗等。
本文介紹使用Springboot2.x+Zookeeper實現簡易的分佈式配置中心,使用Zookeeper存儲配置,本地緩存配置,監聽zookeeper的配置更新,本地實時更新。
1、引入依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<zk.curator.version>2.12.0</zk.curator.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${zk.curator.version}</version>
</dependency>
</dependencies>
2、配置中心類
@Component
public class PropertiesCenter {
/**
* 配置中心
*/
Properties properties = new Properties();
CuratorFramework client = null;
TreeCache treeCache = null;
@Value("${zookeeper.url}")
private String zkUrl;
private final String CONFIG_NAME = "/config-center";
public PropertiesCenter() {
}
private void init() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
client = CuratorFrameworkFactory.newClient(zkUrl, retryPolicy);
treeCache = new TreeCache(client, CONFIG_NAME);
}
/**
* 設置屬性
* @param key
* @param value
* @throws Exception
*/
public void setProperties(String key, String value) throws Exception {
String propertiesKey = CONFIG_NAME + "/" + key;
Stat stat = client.checkExists().forPath(propertiesKey);
if(stat == null) {
client.create().forPath(propertiesKey);
}
client.setData().forPath(propertiesKey, value.getBytes());
}
/**
* 獲取屬性
* @param key
* @return
*/
public String getProperties(String key) {
return properties.getProperty(key);
}
@PostConstruct
public void loadProperties() {
try {
init();
client.start();
treeCache.start();
// 從zk中獲取配置放入本地配置中
Stat stat = client.checkExists().forPath(CONFIG_NAME);
if(stat == null) {
client.create().forPath(CONFIG_NAME);
}
List<String> configList = client.getChildren().forPath(CONFIG_NAME);
for (String configName : configList) {
byte[] value = client.getData().forPath(CONFIG_NAME + "/" + configName);
properties.setProperty(configName, new String(value));
}
// 監聽屬性值變更
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
if (Objects.equals(treeCacheEvent.getType(), TreeCacheEvent.Type.NODE_ADDED) ||
Objects.equals(treeCacheEvent.getType(), TreeCacheEvent.Type.NODE_UPDATED)) {
String updateKey = treeCacheEvent.getData().getPath().replace(CONFIG_NAME + "/", "");
properties.setProperty(updateKey, new String(treeCacheEvent.getData().getData()));
System.out.println("數據更新: "+treeCacheEvent.getType()+", key:"+updateKey+",value:"+new String(treeCacheEvent.getData().getData()));
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、測試的set/get接口
@RestController
public class PropertiesController {
@Autowired
PropertiesCenter propertiesCenter;
@GetMapping("get/{key}")
public String getProperties(@PathVariable String key) {
return propertiesCenter.getProperties(key);
}
@GetMapping("set/{key}/{value}")
public String setProperties(@PathVariable String key, @PathVariable String value) throws Exception {
propertiesCenter.setProperties(key, value);
return "配置成功";
}
}
4、啓動類
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConfigCenterApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterApplication.class, args);
}
}
5、配置application.properties
增加如下內容:
server.port=8080
zookeeper.url=127.0.0.1:2181
6、首先啓動本地的zookeeper,再啓動ConfigCenterApplication
啓動成功後,測試:
瀏覽器訪問:http://127.0.0.1:8080/set/book/java, 設置book的值爲java,
再訪問 http://127.0.0.1:8080/get/book,獲取book的屬性值。