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接口)。

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。

简单说明一下流程:

  • 把配置文件放在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文件:

    yml 复制代码
    member:
      name: "张三 dev" 
  • config-prod.yml文件:

    yml 复制代码
    member:
      name: "李四 prod" 

2. 配置中心服务端搭建

新建springcloud-config模块:

2.1. 引入依赖
xml 复制代码
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-config-server</artifactId>
</dependency>
2.2. 配置文件

bootstrap.yml【或者是application.yml】

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

java 复制代码
@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

3. 客户端

客户端获取配置中心的配置内容。

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

3.1. 引入依赖
xml 复制代码
dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- spring cloud config 客户端 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
</dependencies>

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

3.2. bootstrap.yml

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

复制代码
bootstrap.yml
application-dev.yml
application-dev.yaml
application.yml
application.yaml

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

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从远程仓库获取数据返回给客户端。

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

3.3. 项目启动

访问后可以看到配置中心的配置生效。

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}"

六、实现自动刷新

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

yml 复制代码
member:
    name: "王五-dev"

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

1. actuator方式

1.1. 添加依赖

客户端加入下面依赖:

xml 复制代码
<dependency>
	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
1.2. 配置文件

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

yml 复制代码
management:
  endpoints:
    web:
      exposure:
        include: refresh
1.3. 添加注解

在Controller上添加@RefreshScope注解

java 复制代码
@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

sh 复制代码
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. 在客户端中加入依赖
xml 复制代码
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-bus-amqp</artifactId>
 </dependency>
2.2. 配置文件

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

yml 复制代码
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. 启动客户端

启动多个客户端进行测试:

复制原来客户端:

端口配置:8088

现在我们就启动两个相同的客户端,他们的端口不同:

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的相关配置信息。

相关推荐
别惹CC9 分钟前
Spring AI 进阶之路01:三步将 AI 整合进 Spring Boot
人工智能·spring boot·spring
寒士obj15 分钟前
Spring事物
java·spring
IT毕设实战小研9 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
甄超锋10 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
Java小白程序员13 小时前
Spring Framework:Java 开发的基石与 Spring 生态的起点
java·数据库·spring
甄超锋14 小时前
Java Maven更换国内源
java·开发语言·spring boot·spring·spring cloud·tomcat·maven
还是鼠鼠15 小时前
tlias智能学习辅助系统--Maven 高级-私服介绍与资源上传下载
java·spring boot·后端·spring·maven
还是大剑师兰特16 小时前
Spring面试题及详细答案 125道(1-15) -- 核心概念与基础1
spring·大剑师·spring面试题·spring教程
python_13619 小时前
web请求和响应
java·spring·github
sniper_fandc19 小时前
Spring Cloud系列—Alibaba Sentinel授权与规则管理及推送
spring cloud·sentinel