Skip to content

glh1991/configcenter

 
 

Repository files navigation

配置中心

  1. 简介

配置中心现在基本上是大型互联网公司的标配,用于存储管理公司内部各个系统的配置,降低维护成本。本配置中心提供了:配置管理基本能力、配置发布回滚能力、配置更新推送能力、客户端配置缓存能力、对敏感配置设置访问权限能力。本配置中心的目标是让你能优雅的维护配置。

  1. 环境要求
  • 服务端:jdk1.8
  • 客户端:jdk1.8
  • zookeeper
  • MySQL

注意:本系统已经上传到maven中央库

  1. 演示环境

地址:http://configcenter.antframework.org:6220
超级管理员账号:admin 密码:123
普通管理员账号:normal 密码:123

  1. 技术交流和支持

欢迎进技术交流群一起讨论(加我微信zhong_xun_)。如果本项目对你有帮助,欢迎Star和Fork。

1. 整体设计

配置就是不同应用在不同环境的一些键值对。 整体设计图:

本配置中心内的角色有:服务端、客户端、zookeeper
  • 服务端:管理不同应用在不同环境中的配置,配置数据落地到MySQL数据库。为客户端提供http查询应用在指定环境中的配置。当一个应用在指定环境中的配置有了变更(增删改),则服务端会通过zookeeper通知客户端。

  • 客户端:客户端刚启动时会通过http请求服务端读取当前应用在当前环境中的最新配置。如果从服务端读取失败,则客户端会尝试从本地缓存文件中读取配置,如果本地无缓存文件,则会抛出异常。客户端启动成功后,会监听配置变更事件。当监听到配置有变更时,客户端会再次通过http请求服务端读取最新配置,然后把最新配置保存到缓存文件,最后将最新配置和当前客户端中旧配置进行比较,将变化部分通知给应用。

  • zookeeper:仅仅作为通知工具,并不存储任何配置。当配置有变更,服务端会通知zookeeper,zookeeper接收到消息后会把消息分发给客户端,客户端收到消息后就会调用服务端读取最新配置。即使zookeeper宕机了,客户端也会每5分钟自动上服务端读取最新配置,对zookeeper是弱依赖。

配置可以从应用和环境两个纬度进行共享
  • 应用树:应用树是各个应用之间的继承关系图,类似Java类的继承关系。应用可以多层继承,比如:customer(会员系统)--> core-domain(核心领域)--> common(公共配置)。应用的继承特性可以使不同应用之间共享配置。

  • 环境树:环境树是各个环境之间的继承关系图,类似Java类的继承关系。环境可以多层继承,比如:featureTest1(特性测试环境1)--> test(测试环境)--> offline(线下环境)。环境的继承特性可以使一个应用在不同环境之间共享配置。不同集群在这里可以看成是不同的子环境,而不同集群间往往大部分配置是一样的,只有少数配置是不同的。有了继承特性,新增一个集群只需要进行继承,然后覆盖掉少数的不同配置就可以,而不需要从头开始建配置。

环境树存在的另一个原因:我们使用的环境变成树形结构可能更好。假设你在进行一个特性测试时,为了不影响公共测试环境,你需要单独部署一套独立的测试环境。可能你只修改了系统A,但系统A依赖了系统B和系统C,为了让系统A运行起来,你需要把系统B、C都部署起来。而系统B、C可能还会依赖其他系统,那么为了完整的测试你有可能会部署很多系统。如果你只是修改了系统A很小的一个功能点,为了测试再部署那么多套系统,那就显得得不偿失了。所以如果我们的环境是树形结构(有继承特性),那么你只需要在独立测试环境中部署系统A,当系统A需要调用系统B、C的服务时,只需要先判断当前环境中有没有B、C的服务,如果有则调用当前环境的服务;如果没有则调用父环境(公共测试环境)的服务。要实现这点还需要RPC框架的支持,支持也并不复杂:所有环境的服务注册到统一的一个服务注册中心,每个服务标识自己所在的是哪个环境,然后服务消费者在消费服务前,优先消费当前环境的服务,如果当前环境没有服务,则根据环境继承结构,依次往上查找可用的服务,直到找到为止,然后消费。利用RPC框架的扩展机制,可以完成上述功能。环境树怎么获取?可以直接调用配置中心获取。

每个配置项可以有作用域:私有、可继承、公开
  • 私有:私有的配置只能被当前应用读取,其他应用无法读取,类似Java类的private访问级别字段。这种作用域可以保护配置不被暴露到其他应用。

  • 可继承:可继承的配置既能被当前应用读取,也能被子应用读取,类似Java类的protected访问级别字段。这种作用域方便让同一个继承体系的应用共享配置,也让配置共享不扩大到所有应用。

  • 公开:公开的配置能被所有应用读取,类似Java类的public访问级别字段。这种作用域能方便有些配置可以被所有应用读取,但又不适合将这种配置放到公共配置里。比如当前应用需要提供一个客户端给其他应用使用,而且客户端需要读取当前应用的一些配置,那么这些配置就可以作为公开配置。

每个配置项对普通管理员有访问权限:读写、只读、无

访问权限只约束普通管理员,不会约束超级管理员。运维人员使用超级管理员账号把敏感配置的权限设置为“只读”或“无”,然后给开发人员创建普通管理员账号,让开发人员也能查看和修改非敏感配置(比如一些业务开关配置), 而不需要再通过运维人员。这样既提高了开发人员效率,也减轻了运维人员负担。

  • 读写:普通管理员既能查看该配置项,也能修改该配置项。

  • 只读:普通管理员只能查看该配置项,不能修改该配置项。

  • 无:普通管理员既不能查看该配置项,也不能修改该配置项。

2. 部署服务端

下载服务端。以下是集群部署架构图:

说明:

  • 出于安全考虑,当外网(包括配置管理员)尝试通过http请求访问服务端/config/*路径时,nginx应该进行拦截;而客户端通过内网访问/config/*路径时,nginx应该允许访问。
  • 服务端使用的springboot进行开发,直接命令启动下载好的jar包即可,无需部署tomcat。
  • 有两种方式创建数据库表,根据具体情况选择其中一种方式即可:1、手动执行建表sql;2、让服务端拥有向数据库执行ddl语句权限,服务端第一次启动时会自动建表,无需手动执行sql。
  • 服务端在启动时会在"/var/apps/"下创建日志文件,请确保服务端对该目录拥有写权限。
  • 由于配置中心本身就是用来管理各个环境中的配置,所以大部分公司只需部署两套,一是线下环境配置中心(管理所有非线上环境配置);二是线上环境配置中心(管理线上环境配置)。
  • 线下环境编码:offline,线上环境编码:online(可以根据各公司自己情况自己定义,这里只是根据我个人习惯推荐的两个编码)。
  • 服务端http端口为6220。

启动服务端命令模板:

java -jar configcenter-1.4.0.RELEASE.jar --spring.profiles.active="online" --spring.datasource.url="数据库连接" --spring.datasource.username="数据库用户名" --spring.datasource.password="数据库密码" --meta.zk-urls="配置中心使用的zookeeper地址(IP:端口),如果存在多个zookeeper以英文逗号分隔"

比如我本地测试时启动命令:

java -jar configcenter-1.4.0.RELEASE.jar --spring.profiles.active="offline" --spring.datasource.url="jdbc:mysql://localhost:3306/configcenter-dev?useUnicode=true&characterEncoding=utf-8" --spring.datasource.username="root" --spring.datasource.password="root" --meta.zk-urls="localhost:2181"

3. 集成客户端

读者也可以先看后面的“配置管理介绍”,再来看本部分的客户端介绍。

提供两种方式集成客户端:

  • 直接集成客户端(非spring-boot应用)
  • 通过starter进行集成(spring-boot应用)

3.1 直接集成客户端

客户端提供最核心也是最原子的能力。

3.1.1 引入客户端依赖

<dependency>
  <groupId>org.antframework.configcenter</groupId>
  <artifactId>configcenter-client</artifactId>
  <version>1.4.0.RELEASE</version>
</dependency>

3.1.2 使用客户端

客户端就是Java类,直接new就可以,只是需要传给它相应参数。一个应用可以创建多个客户端,每个客户端之间互不影响。

// 创建客户端
ConfigsContext configsContext = new ConfigsContext(
        "http://localhost:6220",    // 服务端地址
        "customer",                 // 主体应用id
        "dev",                      // 环境id
        "/var/apps/configcenter");  // 缓存文件夹路径

// 获取会员系统的配置
Config customerConfig = configsContext.getConfig("customer");
// 现在就可以获取会员系统的所有配置项了(下面获取redis地址配置)
String redisHost = customerConfig.getProperties().getProperty("redis.host");

// 不仅可以获取会员系统的配置,还可以获取其他应用的配置,不过只能获取其他应用的公开配置,
// 因为当前主体应用为会员系统,现在是以会员系统为视角获取其他应用的配置
// 下面是获取账务系统的公开配置
Config accountConfig = configsContext.getConfig("account");

// 还可以注册配置变更监听器
customerConfig.getListenerRegistrar().register(new ConfigListener() {
    @Override
    public void onChange(List<ChangedProperty> changedProperties) {
        for (ChangedProperty changedProperty : changedProperties) {
            logger.info("监听到会员系统的配置有变更:{}", changedProperty);
        }
    }
});
// 开启配置变更监听功能
configsContext.listenConfigs();

// 系统正常运行...

// 当系统运行结束时,需关闭客户端释放相关资源
configsContext.close();

3.2 通过starter进行集成

starter本质上还是依赖于上面介绍的客户端的能力,只不过根据spring-boot场景提供了更优雅的集成方式,也提供了更方便的功能。

3.2.1 引入starter依赖

<dependency>
  <groupId>org.antframework.configcenter</groupId>
  <artifactId>configcenter-spring-boot-starter</artifactId>
  <version>1.4.0.RELEASE</version>
</dependency>

3.2.2 配置客户端

在应用的配置文件application.properties或application-xxx.properties中配置:

# 必填:应用id(如果未设置,则采用spring.application.name对应的值)
configcenter.app-id=customer
# 必填:服务端地址
configcenter.server-url=http://localhost:6220

# 选填:缓存目录(默认为:/var/apps/configcenter)
configcenter.cache-dir-path=/var/apps/configcenter
# 选填:是否开启监听配置变更事件(默认为开启)
configcenter.listen-configs.enable=true
# 选填:配置刷新周期(单位:秒。默认为5分钟刷新一次)
configcenter.refresh-period=300
# 选填:配置中心的配置优先于指定的配置源(默认为最低优先级)。可填入:commandLineArgs(命令行)、systemProperties(系统属性)、systemEnvironment(系统环境)、applicationConfigurationProperties(配置文件)等等
configcenter.prior-to=applicationConfigurationProperties
# 选填:如果想在日志中打印缓存文件路径,可以进行以下配置
logging.level.org.antframework.configcenter.client.support.ConfigRefresher=debug

3.2.3 使用配置

可以通过spring的@Value注解、environment.getProperty(java.lang.String)获取配置,而不用直接使用客户端。也可以通过ConfigsContexts.getConfig(java.lang.String)获取配置。

// 通过@Value获取配置
@Value("redis.host")
private String redisHost;
@Autowired
private Environment environment;

public void doBiz() {
    // 通过environment获取配置
    String redisHostFromEnvironment = environment.getProperty("redis.host");
    // 通过ConfigsContexts.getConfig(java.lang.String)获取配置
    Config config = ConfigsContexts.getConfig("customer");
    String redisHostFromConfig = config.getProperties().getProperty("redis.host");
}

3.2.4 注册配置变更监听器

可以监听当前应用的配置变更事件:

// 监听当前应用的配置变更事件
@ConfigListener
public class MyConfigListener {
    // 监听所有配置
    @ListenConfigChanged(prefix = "")
    public void listenAll(List<ChangedProperty> changedProperties) {
        // TODO 具体业务代码
    }

    // 监听redis配置(prefix表示需要监听的配置前缀。当以“redis.”开头的配置项被修改时,
    // 被修改的配置会作为入参调用本方法。比如redis.host、redis.port等被修改时都会调用本方法)
    @ListenConfigChanged(prefix = "redis")
    public void listenPool(List<ChangedProperty> changedProperties) {
        // TODO 具体业务代码
    }
    
    // 监听具体某一个配置项(注意:入参不再是List<ChangedProperty>,而是ChangedProperty)
    @ListenConfigChanged(prefix = "redis.host")
    public void listenPool(ChangedProperty changedProperty) {
        // TODO 具体业务代码
    }
}

也可以监听其他应用的公开配置变更事件:

// 监听账务系统的公开配置变更事件
@ConfigListener(appId = "account")
public class MyConfigListener {
    // 监听所有配置
    @ListenConfigChanged(prefix = "")
    public void listenAll(List<ChangedProperty> changedProperties) {
        // TODO 具体业务代码
    }
}

4. 配置管理介绍

进入服务端地址模板:http://IP地址:6220

以下截图有部分未更新,以实际使用为准。

4.1 第一次进入服务端需初始化一个超级管理员

4.2 点击确定,进入初始化页面

4.3 初始化完成后跳转回登录页面,进行登录

4.4 登录成功后,进入配置管理页面

4.5 点击左侧导航栏中的应用一栏,进行应用管理

4.6 点击上图中新增按钮,进行创建应用

4.7 应用有继承关系,而且可以多层继承,类似于java类的单继承,这样的设计可以让我们的配置项的暴露控制在合理的范围。比如下图中的customer(会员系统)--> core-domain(核心领域)--> common(公共配置)

4.8 点击左侧导航栏中的环境一栏,进行环境管理

4.9 点击上图中新增按钮,进行创建环境

4.10 环境管理

4.11 点击左侧导航栏中的配置一栏,进行配置管理

4.12 点击上图中的会员系统,进入配置key管理页面

4.13 点击上图中的新增配置按钮,进行创建配置key。配置key是所有环境共享的,可以指定配置key的作用域:私有、可继承、公开(类似于java类的字段作用域:private、protected、public)

4.14 应用会继承父应用的可继承和公开作用域的配置key。比如会员系统会继承core-domain(核心领域)、common(公共配置)的配置key

4.15 点击上图中的环境,进入对应环境的配置管理,可进行配置修改

4.16 修改配置后,点击"发布修改"按钮,进行发布(配置变更消息会自动推送给应用)

4.17 点击环境下拉框,可以进入其他环境的配置管理页面

4.18 点击发布历史按钮可以进入发布历史页面

4.19 在发布历史页面可看到所有的发布记录、每次发布变更的配置和所有配置

4.20 在发布页面点击回滚按钮可进行回滚

4.21 点击左侧导航栏管理员,会进入管理员管理页面

4.22 点击上图的新增按钮,进行创建管理员。管理员分为两种:超级管理员和普通管理员。超级管理员拥有所有权限可以管理所有应用,普通管理员只能管理被分配给他的应用

4.22 点击左侧导航栏权限,会进入权限管理页面

4.24 点击新增按钮,可以将应用分配给管理员进行管理

4.25 权限分配后如下:

About

配置中心:存储管理各个系统在不同环境中的配置,降低维护成本。

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 49.8%
  • HTML 27.0%
  • JavaScript 22.1%
  • CSS 1.1%