Spring Cloud Config 配置中心
在java开发中难免会涉及到配置文件,比如连接数据库配置、连接一些中间件配置、一些阈值或开关参数等等。我们一般存放到properties或yml文件中,然后应用部署启动的时候读取这些配置项。在分布式系统中,多个服务需要访问和管理配置。如果每个服务都独立管理配置,会导致配置的重复和不一致。另外在不同的环境(如开发、测试、生产)中,应用程序通常需要不同的配置。
Spring Cloud Config 就是为了解决这些问题。Spring Cloud Config 允许将所有服务的配置集中管理在一个地方。这使得配置管理变得更加简单和一致,避免了每个服务单独管理配置的问题。配置中心支持将配置按环境进行隔离(如开发、测试、生产),使得在不同环境下运行的服务能够加载相应的配置。当配置发生变化时,可以通过 Spring Cloud Config 提供的功能进行动态更新。配置客户端可以定期或通过事件驱动的方式自动刷新配置,而无需重新启动应用程序。
Spring Cloud Config 支持多种配置存储方式,包括 Git、SVN、数据库、文件系统等。支持配置的版本管理,使得可以回溯和审查配置的历史版本。下面来看下配置中心的时间使用。
首先Spring Cloud 配置中心是server -client模式进行服务集成。使用 Config Server,你可以在一个中心位置管理所有环境中的应用程序外部配置。应用程序通过Config Client从Server端拉取对用的配置。
Config Server
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
在配置文件中添加配置
#服务端口
server.port=8888
#配置文件生效方式
spring.profiles.active=git
#git 连接参数
#仓库地址
spring.cloud.config.server.git.uri=http://127.0.0.1:8060/cpx/myconfig
#git账户
spring.cloud.config.server.git.username=test
#git密码
spring.cloud.config.server.git.password=test
#默认的git标签或分支
spring.cloud.config.server.git.default-label=master
在config server 中spring.profiles.active用来指定配置文件加载策略,也就是从哪里获取配置文件。默认值是git,也就是从git仓库读取配置文件。spring.cloud.config.server.git.*是git仓库相关的配置。除了上面的基本配置还可以通过searchPaths: 指定在仓库中查找配置文件的路径。cloneOnStart: 启动时是否克隆仓库,默认true。timeout: 连接 Git 仓库的超时时间。
在启动类上加上@EnableConfigServer注解开启Config Server
@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
public static void main(String[] args) {
SpringApplication.run(ConfigServer.class, args);
}
}
假设git上有两个配置文件
hello-dev.yml
cpx:
name: config
age: 20
hello.properties
myserver.name=configserver
myserver.port=8888
这是后访问:http://localhost:8888/hello/dev
会显示如下:
{
"name": "hello",
"profiles": [
"dev"
],
"label": null,
"version": "84084f6ee62aafb5edd6aca58f7c4928538e2a04",
"state": null,
"propertySources": [
{
"name": "http://127.0.0.1:8060/caopengxiang/myconfig/hello-dev.yml",
"source": {
"cpx.name": "config",
"cpx.age": 20
}
},
{
"name": "http://127.0.0.1:8060/caopengxiang/myconfig/hello.properties",
"source": {
"myserver.name": "configserver",
"myserver.port": "8888"
}
}
]
}
默认的属性配置文件定位策略是克隆一个 Git 仓库(在 spring.cloud.config.server.git.uri
中指定),并使用这个仓库初始化一个小型的 SpringApplication
。这个小型应用的 Environment
被用来存储这些配置信息,并在一个 JSON 接口形式发布这些配置文件。
可以通过以下形式来确定属性文件:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
其中application是对应的spring.config.name属性的值,默认是application。
profile指定配置文件所属环境
label指定分支,默认是master。
这和将配置文件存放在工程resources目录下加载方式差不多。
如要精确获取 hello-dev.yml可以通过http://localhost:8888/hello-dev.yml
需要注意下,一般情况下,不带profile的配置文件也会被加载。即如果请求的是/hello/dev。如果hello.properties配置文件存在也会被加载
Config Client
客户端其实也是像上面一样,通过url来进行获取对应的配置
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
这里只需要在client工程里添加spring-cloud-starter-config依赖即可,starter_web是为了测试取值使用。
在配置文件中要指定Config Server的信息
spring.application.name=hello
spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.label=master
spring.cloud.config.profile=prod
这个时候启动client端可能还会遇到一个问题
No spring.config.import property has been defined
Add a spring.config.import=configserver: property to your configuration.
If configuration is not required add spring.config.import=optional:configserver: instead.
To disable this check, set spring.cloud.config.enabled=false or
spring.cloud.config.import-check.enabled=false.
在配置文件按提示添加如下配置即可
spring.config.import=optional:configserver:
启动client端,springboot方式运行,会看到拉取配置的日志:
Fetching config from server at : http://localhost:8888
Located environment: name=hello, profiles=[dev], label=master, version=84084f6ee62aafb5edd6aca58f7c4928538e2a04, state=null
这里name的获取是client端 spring.application.name参数的值,profiles是spring.cloud.config.profile参数的值,label是spring.cloud.config.label参数的值。这样可以确定,能加载到配置文件hello-dev.yml
@SpringBootApplication
public class ConfigClient {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(ConfigClient.class);
System.out.println(ctx.getEnvironment().getProperty("cpx.name"));
System.out.println(ctx.getEnvironment().getProperty("myserver.port"));
}
}
拉取到的配置直接存放到了客户端的Environment里。
其它server配置方式
要修改server端配置载入方式,通过spring.profiles.active来指定,然后在配置对应的参数。其它都不用修改
1、本地文件
spring.profiles.active=native
#指定配置文件目录
spring.cloud.config.server.native.search-locations=D:/doc/study/spring/myconfig/
2、数据库
spring.profiles.active=jdbc
spring.cloud.config.server.jdbc.default-label=master
spring.cloud.config.server.jdbc.sql=SELECT `key`,`value` FROM properties WHERE application=? AND PROFILE=? AND label=?
数据库这里要提前准备一张配置表,表主要以key,value形式存储配置参数,另外还有环境和服务相关的application,profile,label列。
CREATE TABLE properties (
application VARCHAR(255),
profile VARCHAR(255),
label VARCHAR(255),
key VARCHAR(128),
value VARCHAR(255),
PRIMARY KEY (application, profile, label, key)
);
当然工程要添加数据库连接的依赖以及配置
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
jdbc连接配置
spring.datasource.url=jdbc:mysql://localhost:3306/config_server
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
然后在上面的配置表中添加对应的配置,client端就可以拉取对应的配置了。
自动刷新
如果想server端更新配置后,client端在不重启应用的情况下,自动获取到更新后的配置并运用,可以进行以下操作。
下面的操作都是在client端,spring cloud config server不提供自动刷新。
这里要借助spring boot的actuator
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后添加配置
management:
endpoints:
web:
exposure:
include: refresh
这里启用了actuator的refresh服务端点,可以通过访问/actuator/refresh就可以刷新配置
在后写一个测试controller来验证自动刷新
@RestController
@RefreshScope
public class TestController {
@Value("${cpx.name}")
private String name;
@RequestMapping("/hello")
public String m1(){
return name;
}
}
在需要自动刷新配置的bean上一定要添加**@RefreshScope**注解,这样当访问/actuator/refresh的时候才会自动刷新对应的值。
!!!这里需要注意一下, http://localhost/8080/actuator/refresh 这个刷新接口的访问一定要用POST方式,浏览器get方式是访问不到的。