SpringCloud Config配置中心详解及环境搭建

前言

我们之前介绍并且搭建过eurekazuulhystrix组件。本节介绍的config是SpringCloud五大组件的最后一个,还有一个是Ribbon ----- 客服端负载均衡,之前我们有简单介绍过☞Eureka、Nacos注册中心及负载均衡原理,直接使用注解@LoadBalanced就可以实现负载均衡或者是网关zuul默认带有负载均衡策略、gateway使用lb。本节我们来介绍下config作用及环境搭建。

一、配置中心作用

微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以也面临了一些问题:

  • 随着微服务工程的越来越多,每个工程都有一套配置文件,系统膨胀;
  • 如果每个项目都有公共的比如数据库链接信息,没有统一的管理,想要修改则需要每个工程都要修改;
  • 我们通常有很多系统环境:如prod(生产环境)、test(测试环境)、dev(预发布环境)

所以一套集中式的、动态的配置管理设施是必不可少的。

二、常见的配置中心

目前使用较多的三套配置:

  • Config+Bus

  • Nacos(后起之秀,我们之前已经介绍过了)

  • 携程阿波罗(Apollo)

三、Config的作用

  • 集中管理配置
    Spring Cloud Config 可以将应用程序的配置文件集中管理起来,以便在不同环境下轻松部署和管理应用程序。开发人员可以将配置文件存储在 Git、SVN 或本地文件系统等存储库中,并使用 Spring Cloud Config 服务器来访问和管理这些文件。

  • 多环境支持
    Spring Cloud Config 支持多环境配置文件的管理,开发人员可以将不同环境下的配置文件分别存储在不同的存储库中,并在应用程序启动时根据不同的环境加载相应的配置文件,分环境部署比如dev/test/prod/beta/release

  • 动态刷新配置
    Spring Cloud Config 还支持动态刷新配置,当应用程序运行时,开发人员可以通过调用 REST 接口来刷新配置,或者在配置中心修改配置文件后自动更新应用程序的配置。

  • 安全性控制
    Spring Cloud Config 提供了基于角色的安全性控制,开发人员可以通过配置用户角色来限制对配置文件的访问权限,确保只有授权用户才能访问敏感信息。

四、Config架构

SpringCloud Config分为服务端客户端两部分。

服务端也称为分布式配置中心,它是一个独立的微服务应用,为客户端提供配置信息,加密/解密信息等访问接口。服务器为外部配置(名称值对或等效的YAML内容)提供了基于资源的HTTP(REST接口)。

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。
SpringCloud Config配置中心详解及环境搭建_第1张图片
简单说明一下流程:

  • 把配置文件放在Git Repository中
  • Config Server从Git repository中读取配置信息
  • 其他客户端再从Config Server中加载配置文件

五、实战案例

在我们之前的eureka或者zuulhystrix项目上进行开发,省去繁琐的项目创建步骤。但各个组件之间并没有依赖关系,config也一样,完全可以新建一个项目按我的步骤开发。

项目中使用到的版本:

  • Spring Boot:2.3.12.RELEASE(2.2.X版本或者2.3.X版本)
  • Spring Cloud:Hoxton.SR1

1. 创建配置中心仓库

首先我们需要一个创建一个配置中心仓库。可以使用github或者是码云gitee。

1、在码云创建springcloud-config仓库,并创建以下两个文件:

文件命名规格:{项目名}-{配置环境版本}.yml。比如config-dev.yml,表示的是config项目的开发环境配置。

  • config-dev.yml文件:
    member:
      name: "张三 dev" 
    
  • config-prod.yml文件:
    member:
      name: "李四 prod" 
    
    SpringCloud Config配置中心详解及环境搭建_第2张图片

2. 配置中心服务端搭建

新建springcloud-config模块:

2.1. 引入依赖
<dependency>
	<groupId>org.springframework.cloudgroupId>
	<artifactId>spring-cloud-config-serverartifactId>
dependency>
2.2. 配置文件

bootstrap.yml【或者是application.yml】

spring:
  application:
    name: config-server  # 应用名称
  cloud:
    config:
      server:
        git:
          # 配置中心仓库地址
          uri: https://gitee.com/lin-shen/springcloud-config.git #配置文件所在仓库
          username: 码云用户名
          password: 码云密码
          default-label: master #配置文件分支
server:
    port: 9999

bootstrap.yml文件

applicaiton.yml是用户级的资源配置项,bootstrap.yml是系统级的,优先级更加高

要将Client模块下的application.yml文件改为bootstrap.yml,这是很关键的。因为bootstrap.yml是比application.yml先加载的。

Spring Cloud会创建一个“Bootstrap Context”,作为Spring应用的Application Context的父上下文。初始化的时候,Bootstrap Context负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的’Environment’。

Bootstrap属性有高优先级,默认情况下,它们不会被本地配置覆盖。Bootstarp context 和 Application Context 有着不同的约定,所以新增了一个bootstrap.yml文件,保证Bootstrap Context和Application Context配置的分离。

2.3. 启动类

在 Application 启动类上增加相关注解 @EnableConfigServer

@SpringBootApplication
@EnableConfigServer
public class SpringcloudConfigApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringcloudConfigApplication.class, args);
	}
}
2.4. 测试服务

启动SpringBoot服务,测试一下。

SpringCloud Config 有它的一套访问规则,我们通过这套规则在浏览器上直接访问就可以。

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
  • application:应用名,这里是config
  • profile:配置文件版本,比如dev、prod
  • label:git的分支,默认master

SpringCloud Config配置中心详解及环境搭建_第3张图片

3. 客户端

客户端获取配置中心的配置内容。
在之前项目的provider-server模块或者是创建一个新的模块获取配置中心的相关配置:

3.1. 引入依赖
dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-configartifactId>
    dependency>
dependencies>

注意,客户端和服务端引入的config依赖是不一样的。

3.2. bootstrap.yml

由于配置文件的加载优先级不同,Spring Boot会尝试加载以下配置文件(按照优先级从高到低):

bootstrap.yml
application-dev.yml
application-dev.yaml
application.yml
application.yaml

高的配置生效后,低的不会生效。获取配置中心的配置,应该在bootstrap.yml配置文件中进行配置才能确保获取得到配置中心的数据。

---
spring:
  profiles:
    active: dev
---
spring:
  profiles: dev
  application:
    name: config
  cloud:
    config:
      uri: http://localhost:9999
      label: master
      profile: dev
---
spring:
  profiles: prod
  application:
    name: config
  cloud:
    config:
      uri: http://localhost:9999
      label: master
      profile: prod

该配置文件指定了加载dev配置信息,会向配置中心服务端即http://locahost:9999服务发起请求获取配置,服务端则发起请求http://localhost:9999/config/dev从远程仓库获取数据返回给客户端。
SpringCloud Config配置中心详解及环境搭建_第4张图片

这里遇到了一个奇怪的错误,有时候启动时,当resources文件下有其他配置文件时会干扰从远程仓库获取配置数据,即使远程仓库有member.name="张三-dev"配置也会报错,解决方法就是resources目录删除到只剩下bootstrap.yml文件。

3.3. 项目启动

访问后可以看到配置中心的配置生效。
SpringCloud Config配置中心详解及环境搭建_第5张图片

3.4. 问题

我们上面提到的配置文件方式是多个配置环境写到同一个文件中,但这样维护非常繁琐,不同的环境就应该有对应的一个配置文件,但这种配置方式下配置中心的配置不生效,必须要本地文件配置member.name,不配置会报以下错误:找不到member.name属性。

Error creating bean with name ‘userController’: Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder ‘member.name’ in value “${member.name}”

SpringCloud Config配置中心详解及环境搭建_第6张图片

六、实现自动刷新

Spring Cloud Config是在项目启动的时候加载的配置内容,导致了它存在一个缺陷,配置文件修改后,需要重启服务才能生效。我们在码云上修改config-dev.yml配置:

member:
    name: "王五-dev"

虽然访问http://localhost:9999/config/dev从之前的张三变成了王五,但是访问http://localhost:8082/user/login还是张三,说明配置没有自动刷新,可以通过 @RefreshScope 注解并结合 actuator实现自动刷新。

1. actuator方式

SpringCloud Config配置中心详解及环境搭建_第7张图片

1.1. 添加依赖

客户端加入下面依赖:

<dependency>
	<groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-actuatorartifactId>
dependency>
1.2. 配置文件

在application.yml中添加如下actuator的配置

management:
  endpoints:
    web:
      exposure:
        include: refresh
1.3. 添加注解

在Controller上添加@RefreshScope注解

@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {

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

    @GetMapping("/login")
    public String login(){
        return "8080 " + name + " login success";
    }
}
1.4. 更新配置请求

当配置文件发生更改时,可以通过向应用程序发送POST请求来触发配置刷新。默认情况下,刷新端点的路径为/actuator/refresh。可以在cmd窗口使用curl命令发送POST请求:

注意:要向客户端发起请求,端口是8082,而不是服务端:9999

curl -X POST http://localhost:8082/actuator/refresh

2. SpringCloud Bus实现

上面提到的actuator方式,如果每次配置文件修改后,都需要我们主动发送post请求触发更新,这明显有点不太方便。而且如何客户端比较多的话,一个一个的手动刷新也很耗时。这个时候,我们可以借助Spring Cloud Bus的广播功能,让client端都订阅配置更新事件,当配置更新时,触发其中一个端的更新事件,Spring Cloud Bus就把此事件广播到其他订阅端,以此来达到批量更新。

Spring Cloud Bus 核心原理其实就是利用消息队列做广播,所以要先有个消息队列,目前官方支持 RabbitMQ 和 kafka。我们这里以RabbitMQ 为例。

在actuator方式配置下进行以下配置的修改

2.1. 在客户端中加入依赖
<dependency>
     <groupId>org.springframework.cloudgroupId>
     <artifactId>spring-cloud-starter-bus-amqpartifactId>
 dependency>
2.2. 配置文件

在配置文件中进行以下配置,我们在上面说过使用RabbitMQ作为广播,rabbitmq可以参考:rabbitmq安装。

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
management:
  endpoints:
    web:
      exposure:
        include: bus-refresh
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: ldh
    password: ldh
  cloud:
    bus:
      enabled: true
2.3. 启动客户端

启动多个客户端进行测试:
复制原来客户端:
SpringCloud Config配置中心详解及环境搭建_第8张图片
端口配置:8088
SpringCloud Config配置中心详解及环境搭建_第9张图片
现在我们就启动两个相同的客户端,他们的端口不同:
SpringCloud Config配置中心详解及环境搭建_第10张图片

2.4. 访问服务

分别打开http://localhost:8099/user/loginhttp://localhost:8082/user/login,查看内容,然后修改码云上配置文件的内容并提交。再次访问这两个地址,数据没有变化。

在cmd窗口访问访问其中一个的 actuator/bus-refresh 地址:curl -X POST http://localhost:8082/actuator/bus-refresh

再次访问这两个地址,会看到内容都已经更新为修改后的数据了,相比actuator方式只需一次post请求即可刷新各个客户端访问服务端config的相关配置信息。

你可能感兴趣的:(SpringCloud,spring,cloud,spring,config)