代码已提交至Github,有兴趣的同学可以下载来看看(git版本号:​3f3d5e73d533c5ac9f92e0d21192e50149e39cb9​):https://github.com/ylw-github/SpringBoot-Zookeeper-Demo

1.分布式配置中心

什么是分布式配置中心?

  • 项目中配置文件比较繁杂,而且不同环境的不同配置修改相对频繁,每次发布都需要对应修改配置,如果配置出现错误,需要重新打包发布,时间成本较高,因此需要做统一的分布式注册中心,能做到自动更新配置文件信息,解决以上问题。

常用分布式配置中心框架有哪些呢?

  • ​disconf​(推荐),可支持KV存储以及配置文件形式存储,使用和开发更为简便。并且本身也是基于zookpeer的分布式配置中心开发,方便部署使用,并且支持实时更新通知操作,但是部署相对复杂。
  • ​Diamond(daɪəmənd)​基本可以放弃,一般做KV的存储配置项,做配置文件不是很好的选择。
  • ​Spring Cloud Config​因为依赖git,使用局限性较大,需要在各个环境中安装git,并且不支持KV存储,功能方面略差于disconf。

分布式配置中心实现原理对比:

注册中心

配置存储

时效性

数据模型

维护性

优点

缺点

disconf

zookpeer

实时推送

支持传统的配置文件模式,亦支持KV结构数据

提供界面操作

基于分布式的Zookeeper来实时推送稳定性、实效性、易用性上均优于其他

源码较多,阅读和使用起来相对较复杂

zookpeer

zookpeer

实时推送

支持传统的配置文件模式,亦支持KV结构数

命令操作

实时推送稳定性、实效性

开发量大

diamond

mysql

每隔15s拉一次全量数据

只支持KV结构的数据

提供界面操

简单、可靠、易用

数据模型不支持文件,使用不方便

Spring Cloud Config

git

人工批量刷新

文件模式

git操作

简单、可靠、易用

需要依赖GIT,并且更新GIT

2.基于Zookeeper实现分布式配置中心

1.添加maven依赖:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

2.application.yml

server:
port: 8080
#port: 8081
#port: 8082
user:
key: ylw

3.ConfigUtils

package com.ylw.zookeeper.center;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class ConfigUtils {
@Value("${user.key}")
private String userKey;

public String getUserKey() {
return userKey;
}

public void setUserKey(String userKey) {
this.userKey = userKey;
}
}

4.MyApplicationRunner(项目启动创建zk节点):

package com.ylw.zookeeper.center;

import org.I0Itec.zkclient.IZkDataListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationRunner extends BaseZookeeper implements ApplicationRunner {

@Autowired
private ConfigUtils configUtils;

// 启动后执行方法
public void run(ApplicationArguments args) throws Exception {
System.out.println("项目启动成功...");
String userValue = configUtils.getUserKey();
String userKey = "/userKey";
try {
// 创建节点信息
zkClient.createEphemeral(userKey, userValue);
} catch (Exception e) {
e.printStackTrace();
}
zkClient.subscribeDataChanges(userKey, new IZkDataListener() {
public void handleDataDeleted(String dataPath) throws Exception {
}

// 当值发生变化的时候
public void handleDataChange(String dataPath, Object data) throws Exception {
System.out.println("dataPath:" + dataPath + ",data:" + data);
final String strData = (String) data;
configUtils.setUserKey(strData);
}
});

}

}

5.UpdateInfoService(修改Zookeeper节点信息):

package com.ylw.zookeeper.center;

import org.springframework.stereotype.Service;

@Service
public class UpdateInfoService extends BaseZookeeper {
public String updateInfo(String key, String value) {
try {
zkClient.writeData("/" + key, value);
return "success";
} catch (Exception e) {
return "fail";
}
}
}

6.IndexController(获取配置文件信息):

package com.ylw.zookeeper.center;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {
@Autowired
private ConfigUtils configUtils;

@Autowired
private UpdateInfoService updateInfoService;

@RequestMapping("/getInfo")
public String getInfo() {
return configUtils.getUserKey();
}

@RequestMapping("/updateInfo")
public String updateInfo(String key, String value) {
String updateInfo = updateInfoService.updateInfo(key, value);
return updateInfo;
}
}

未完待续。。。