一、配置中心简介

1、概述

对于传统的单体应用而言,常使用配置文件来管理所有配置,比如SpringBoot的application.yml文件,但是在微服务架构中全部手动修改的话很麻烦而且不易维护。微服务的配置管理一般有以下需求:

  • 集中配置管理,一个微服务架构中可能有成百上千个微服务,所以集中配置管理是很重要的。
  • 不同环境不同配置,比如数据源配置在不同环境(开发,生产,测试)中是不同的。
  • 运行期间可动态调整。例如,可根据各个微服务的负载情况,动态调整数据源连接池大小等
  • 配置修改后可自动更新。如配置内容发生变化,微服务可以自动更新配置

综上所述对于微服务架构而言,一套统一的,通用的管理配置机制是不可缺少的总要组成部分。常见的做法就是通过配置服务器进行管理。

2、常见配置中心

Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。

  • 1、Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
  • 2、Disconf 专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」包括 百度、滴滴出行、银联、网易、拉勾网、苏宁易购、顺丰科技 等知名互联网公司正在使用

3、springcloud config简介

Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用

 

 

 

Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以为所有环境中的应用程序管理其外部属性。它非常适合spring应用,也可以使用在其他语言的应用上。随着应用程序通过从开发到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。

Spring Cloud Config服务端特性:

  • HTTP,为外部配置提供基于资源的API(键值对,或者等价的YAML内容)
  • 属性值的加密和解密(对称加密和非对称加密)
  • 通过使用@EnableConfigServer在Spring boot应用中非常简单的嵌入。
  • Config客户端的特性(特指Spring应用)
  • 绑定Config服务端,并使用远程的属性源初始化Spring环境。
  • 属性值的加密和解密(对称加密和非对称加密)

二、springcloud config入门

Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git存储配置文件内容,也可以使用SVN存储,或者是本地文件存储。

1) 搭建服务端

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
    </dependencies>

添加启动类:

@SpringBootApplication
@EnableConfigServer
public class ConfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigApplication.class,args);
    }
}

@EnableConfigServer : 通过此注解开启注册中心服务端功能

配置application.yml

server:
  port: 10001 #服务端口
spring:
  application:
    name: config-server #指定服务名
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/xiaodtest/testconfig.git

浏览器访问git文件:http://localhost:10001/application-dev.yml

2)修改客户端程序

引入依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

删除application.yml,添加bootstrap.yml

spring:
cloud:
config:
name: application #应用名称,需要对应git中配置文件名称的前半部分
profile: dev #开发环境
label: master #git中的分支
uri: http://localhost:10001 #config-server的请求地址

启动product-service,可成功访问相关服务

3)手动刷新

我们已经在客户端取到了配置中心的值,但当我们修改GitHub上面的值时,服务端(Config Server)能实时获取最新的值,但客户端(Config Client)读的是缓存,无法实时获取最新值。SpringCloud已经为我们解决了这个问题,那就是客户端使用post去触发refresh,获取最新数据,需要依赖springboot-starter-actuator

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

对应的controller类加上@RefreshScope

@RestController
@RequestMapping("/product")
@RefreshScope
public class ProductController {
    @Autowired
    private ProductService productService;

    @Value("${server.port}")
    private String port;

    @Value("${spring.cloud.client.ip-address}") //spring cloud 自动的获取当前应用的ip地址
    private String ip;

    @Value("${name}")
    private String name;

    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    public Product findById(@PathVariable Long id) {
        Product product = productService.findById(id);
        product.setProductName("访问的服务地址:"+ip + ":" + port);
        return product;
    }

    @GetMapping(value = "/testName")
    public String testName() {
        return name;
    }
}

客户端配置文件添加端点:

management:
  endpoints:
    web:
      exposure:
        include: refresh

postman中发送post请求:http://localhost:9001/actuator/refresh,访问数据发现已发生变化

三、配置中心的高可用

在之前的代码中,客户端都是直接调用配置中心的server端来获取配置文件信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念。springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可。

1)服务端改造:

添加依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

修改配置文件添加如下配置:

eureka:
  client:
    serviceUrl:
      defaultZone: http://127.0.0.1:9000/eureka/
  instance:
    preferIpAddress: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port} #spring.cloud.client.ip-address:获取ip地址

2)客户端改造:

添加依赖:

       <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

修改配置文件:

spring:
  cloud:
    config:
      name: application #应用名称,需要对应git中配置文件名称的前半部分
      profile: dev #开发环境
      label: master #git中的分支
#      uri: http://localhos/t:10001 #config-server的请求地址
      #通过注册中心获取config-server配置
      discovery:
        enabled: true #开启服务发现
        service-id: config-server
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/
  instance:
    prefer-ip-address: true #使用ip地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

四、消息总线

在微服务架构中,通常会使用轻量级的消息代理来构建一个共用的消息主题来连接各个微服务实例,它广播的消息会被所有在注册中心的微服务实例监听和消费,也称消息总线。SpringCloud中也有对应的解决方案,SpringCloud Bus 将分布式的节点用轻量的消息代理连接起来,可以很容易搭建消息总线,配合SpringCloud config 实现微服务应用配置信息的动态更新。

根据此图我们可以看出利用Spring Cloud Bus做配置更新的步骤:

  • 提交代码触发post请求给bus/refresh
  • server端接收到请求并发送给Spring Cloud Bus
  • Spring Cloud bus接到消息并通知给其它客户端
  • 其它客户端接收到通知,请求Server端获取最新配置
  • 全部客户端均获取到最新的配置

 消息总线整合配置中心:

1)引入依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--消息总线的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-bus</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
        </dependency>

服务端配置:

server:
  port: 10000 #服务端口
spring:
  application:
    name: config-server #指定服务名
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/it-lemon/config-repostory.git
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
management:
  endpoints:
    web:
      exposure:
        include: bus-refresh
eureka:
  client:
    serviceUrl:
      defaultZone: http://127.0.0.1:9000/eureka/
  instance:
    preferIpAddress: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port} #spring.cloud.client.ip-address:获取ip地址

客户端配置:

spring:
  cloud:
    config:
      name: product #应用名称,需要对应git中配置文件名称的前半部分
      profile: pro #开发环境
      label: master #git中的分支
      #uri: http://localhost:10000 #config-server的请求地址
      #通过注册中心获取config-server配置
      discovery:
        enabled: true #开启服务发现
        service-id: config-server
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/
  instance:
    prefer-ip-address: true #使用ip地址注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

git 配置中添加rabbitmq的配置信息

重新启动对应的eureka-server , config-server , product-service。配置信息刷新后,只需要向配置中心发送对应的请求,即可刷新每个客户端的配置