1 Star 0 Fork 160

物欲心扉 / bridge

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

Bridge

配置中心 · 管理系统

全量/灰度下发、实例配置项订阅的实时监控、发布回滚、操作日志、配置项监听、权限控制、多环境切换

演示地址( 账号:test 密码:test )

目录

开发背景

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

主要功能

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

使用到的一些技术

  • Springboot、Mybatis、Maven
  • Zookeeper
  • Mysql
  • Vue.js + Element + iView

操作界面展示

  • 工作台

    工作台页面

  • 账号管理

    账号管理

  • 团队管理

    团队管理

  • 系统管理

    系统管理

  • 配置项管理

    配置项管理

  • 操作日志

    操作日志

  • Zookeeper

    Zookeeper

框架原理

  • 原理图 原理图

控制台搭建

  • 首先需要准备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包运行即可

  • 至此,配置中心后台管理系统搭建完成

客户端接入

  • 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") 注解,还是会存在不一致性读的问题,所以此种方式不推荐用户使用

  • 如何使用监听


在介绍完接入的方法后,接下来我们一起来看看如何添加对指定配置项的监听,可以参考下面的例子
   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 可以传入一个数组,当有值传入的时候则会监听传入的配置项,如果不传任何参数则监听所有的配置项。

项目更新日志

2019-03-19 v1.0.0
  • 项目开发、测试完成
2019-08-23 v1.0.1
  • 通过调整webpack打包方式,优化前端访问页面的速度,由原来的1.5min提升至600ms左右
  • 优化了一些代码,使其更符合阿里规约
  • 更改项目logo

空文件

简介

基于zookeeper实现的一个配置中心系统,可以动态发布配置项,客户端系统订阅后可以即时感知,无需重启服务 展开 收起
Java
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/zzhignore/bridge.git
git@gitee.com:zzhignore/bridge.git
zzhignore
bridge
bridge
master

搜索帮助