什么是配置中心 (配置中心设计)

游戏问答 2023-05-01 09:31:46

开发背景

本项目主要是为了解决分布式系统中配置杂乱,无法集中管理,和频繁修改配置项后需要重新发布服务的问题。目前提供了“全量/灰度发布、客户端实例配置项订阅情况实时监控、发布回滚、操作历史日志、配置项监听、权限控制、多环境切换(开发、测试、预发、生产)"等功能。

主要功能

秒级下发配置项,客户端系统动态更新配置项无需重新发布完整的权限体系账号分为三种角色,权限依次递减:系统管理员、团队管理员、普通用户系统管理员可以操作所有团队下的系统和账号团队管理员只可以操作自己团队下的系统和团队成员的账号普通用户只可以操作自己负责的系统记录配置文件操作历史,提供版本回退,减少误操作带来的影响实时监控客户端实例对配置项订阅的情况只需部署一台服务即可,支持多环境切换,不需要dev、test、stable、online各部署一台解决在下发配置项,用户正在读取配置项时发生的“不一致性读”的问题兼容原生的Spring的@Value注解,同时支持 注解 和 XML占位符 获取配置项对指定的配置项或全部的配置提供监听,方便业务扩展代码侵入性低,集成、部署简单友好的控制台操作页面

使用到的一些技术

Springboot、Mybatis、MavenZookeeperMysqlVue.js + Element + iView + Ant Design of Vue

操作界面展示

工作台
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第1张
账号管理
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第2张
团队管理
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第3张
系统管理
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第4张
配置项管理
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第5张
操作日志
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第6张
Zookeeper
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第7张

框架原理

原理图
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第8张

控制台搭建

首先需要准备node.js环境,具体可以参考链接http://www.runoob.com/nodejs/nodejs-install-setup.html准备zookeeper环境,关于如何安装zookeeper,可以参考下面的链接https://www.cnblogs.com/Lzf127/p/7155316.html导入Mysql脚本,修改 application.properties 相关配置参数然后进入到模块bridge-console下的doc文件夹下运行脚本进行打包,注意这里不要挪动该脚本的位置sh bridge-package.sh 然后将打包好的Jar包运行即可,默认的系统管理员账号为admin,密码为admin至此,配置中心后台管理系统搭建完成

客户端接入

Springboot项目的接入

本项目中提供了配置中心的springboot版本的starter包,对于springboot项目接入非常简单,只需要引入starter包,并在application.properties文件中做简单配置即可。

在 pom 中引入以下依赖包 <dependency> <groupId>com.bridge</groupId> <artifactId>bridge-spring-boot-starter</artifactId> <version>${最新的版本号}</version> </dependency> 在 application.properties 文件中添加配置项 # 系统编码,在控制台新建项目后将该参数配置在此处 spring.bridge.app-code = 294a-56c4-4f18-80df # 控制台的服务地址 spring.bridge.server-url = http://localhost:8080/bridge # 环境配置,支持开发、测试、预发、生产 四种环境切换 spring.bridge.env-enum = dev 普通Spring项目的接入在 pom 中引入jar包 <dependency> <groupId>com.bridge.core</groupId> <artifactId>bridge-core</artifactId> <version>${最新的版本号}</version> </dependency> 新建一个 xml 配置文件 bridge-config.xml ,写入以下配置后加入Spring中 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <aop:aspectj-autoproxy proxy-target-class="true"/> <bean class="com.bridge.consistency.aop.BridgeAspect"/> <bean id="bridgeConfigBeanPostProcessor" class="com.bridge.processor.BridgeConfigBeanPostProcessor"> <constructor-arg name="bridgeConfig" ref="beanConfig"/> </bean> <bean id="beanConfig" class="com.bridge.domain.BridgeConfig"> <property name="serverUrl" value="${控制台的服务地址}"/> <property name="appCode" value="${系统编码}"/> <property name="envEnum" value="${环境}"/> </bean> </beans> 至此接入工作已经全部完成,下面继续看如何使用它

如何使用

首先我们登录控制台,在指定的团队下新建一个系统A,并指定一个账号作为系统负责人,接着我们将系统A的 系统编码 配置在对应的客户端系统中,然后开始添加客户端系统需要的配置项。这里需要注意的是该配置项第一次新增完成后,点击 下发 时为 全量下发,如果不点击 下发 ,则客户端无法感知到该配置项。如果配置项是已经存在的,做变更操作,这时候是支持灰度下发的,因为此时已经有客户端系统的实例订阅了该配置。 经过上面的操作后,我们已经成功在控制台新建好了配置项,接下来我们一起看下如何在客户端系统中使用这个配置项

通过注解的方式使用 (推荐的使用方式) package com.sample.springboot; import com.bridge.annotation.BridgeValue; import lombok.Data; import org.springframework.stereotype.Component; import java.math.BigDecimal; /** * @author Jay * @version v1.0 * @description 请添加类描述 * @date 2019-01-16 14:33 */ @Data @Component public class TestComponent { public String abString; public Integer abInteger; public BigDecimal abBigDecimal; public Long abLong; public Short abShort; public Double abDouble; public Float abFloat; public Boolean abBoolean; @BridgeValue(key = "string", propertyName = "abString") public String getAbString() { return abString; } @BridgeValue(key = "integer", propertyName = "abInteger") public Integer getAbInteger() { return abInteger; } @BridgeValue(key = "bigDecimal", propertyName = "abBigDecimal") public BigDecimal getAbBigDecimal() { return abBigDecimal; } @BridgeValue(key = "long", propertyName = "abLong") public Long getAbLong() { return abLong; } @BridgeValue(key = "short", propertyName = "abShort") public Short getAbShort() { return abShort; } @BridgeValue(key = "double", propertyName = "abDouble") public Double getAbDouble() { return abDouble; } @BridgeValue(key = "float", propertyName = "abFloat") public Float getAbFloat() { return abFloat; } @BridgeValue(key = "boolean", propertyName = "abBoolean") public Boolean getAbBoolean() { return abBoolean; } }

接下来我们可以使用了

@Autowired private TestComponent testComponent; @RequestMapping("/test") @ResponseBody public Result<BigDecimal> test() { BigDecimal data = testComponent.getAbBigDecimal(); return RpcResponse.wrapSuccessfulResult(data); } 两点需要注意的地方

1.其中注解 @BridgeValue(key = "boolean", propertyName = "abBoolean") 中的 key 为配置项名称,propertyName 为成员变量名称。

2.特别需要注意的是不要将配置项直接在使用的地方直接配置,具体看下面的例子。

package com.sample.springboot; import com.bridge.annotation.BridgeValue; import lombok.Data; import org.springframework.stereotype.Service; /** * @author Jay * @version v1.0 * @description 请添加类描述 * @date 2019-01-16 14:33 */ @Data @Service public class TestService { public String abString; @BridgeValue(key = "string", propertyName = "abString") public String getAbString() { return abString; } /** * 不要直接在TestService内引入该配置项后直接在这里使用, * 因为spring的aop无法拦截到上面getAbString()方法, * 这样做虽然可以获取到最新值,但会存在“不一致性读的”隐患 * * @return */ public String say(){ return "say: ".concat(getAbString()).concat(getAbString()); } } 通过XML的方式使用

当上面这个TestBO的所有成员变量为配置项时,我们可以通过在xml中配置bean的方式去实现配置,请看下面的这个例子

<bean id="testBO" class="com.sample.springboot.TestBO"> <property name="abString" value="@Bridge{string}"/> <property name="abBigDecimal" value="@Bridge{bigDecimal}"/> <property name="abDouble" value="@Bridge{double}"/> <property name="abFloat" value="@Bridge{float}"/> <property name="abInteger" value="@Bridge{integer}"/> <property name="abLong" value="@Bridge{long}"/> <property name="abShort" value="@Bridge{short}"/> <property name="abBoolean" value="@Bridge{boolean}"/> </bean>

只要使用 @Bridge{配置项} 即可。通过 XML 的方式使用时,如果没有办法在对应成员变量所在的类中添加对应的get方法并添加 @BridgeValue(key = "xxx.xx", propertyName = "xxxx") 注解,还是会存在不一致性读的问题,所以此种方式不推荐用户使用。

如何使用监听
什么是配置中心   (配置中心设计)_https://www.ybmzs.com_游戏问答_第9张

在介绍完接入的方法后,接下来我们一起来看看如何添加对指定配置项的监听,可以参考下面的例子

package com.sample.springboot; import com.bridge.annotation.BridgeValueChangedListener; import com.bridge.listener.PropertiesChangeListener; import com.bridge.zookeeper.data.ConfigKeyNodeData; import lombok.extern.slf4j.Slf4j; /** * @author Jay * @version v1.0 * @description 请添加类描述 * @date 2019-02-19 14:49 */ @Slf4j @BridgeValueChangedListener(key = "test.one.two") public class ListenerTest implements PropertiesChangeListener { /** * 当值发生变化前 * * @param configKeyNodeData */ @Override public void onBeforePropertiesChanged(ConfigKeyNodeData configKeyNodeData) { log.info("当值发生变化前,接收到回调------>:{}", configKeyNodeData); } /** * 当值发生变化后 * * @param configKeyNodeData */ @Override public void onPropertiesChanged(ConfigKeyNodeData configKeyNodeData) { log.info("接收到回调------>:{}", configKeyNodeData); } }

这里注解 @

BridgeValueChangedListener(key = "test.one.two") 中的 key 可以传入一个数组,当有值传入的时候则会监听传入的配置项,如果不传任何参数则监听所有的配置项。

私信回复"bridge"获取链接地址,喜欢的点个关注,一起学习探讨新技术。

发表回复