走进Spring Cloud之八 SpringCloud Config(配置中心)(Greenwich版本)
Spring Boot profile
在Spring Boot应用中,我们可以将配置内容写入application.yml
,设置多个profile
,也可以用多个application-{profile}.properties
文件配置,并在启动时指定--spring.profiles.active={profile}
来加载不同环境下的配置。
在Spring Cloud微服务架构中,这种方式未必适用,微服务架构对配置管理有着更高的要求,如:
- 集中管理:成百上千(可能没这么多)个微服务需要集中管理配置,否则维护困难、容易出错;
- 运行期动态调整:某些参数需要在应用运行时动态调整(如连接池大小、熔断阈值等),并且调整时不停止服务;
- 自动更新配置:微服务能够在配置发生变化是自动更新配置。
以上这些要求,传统方式是无法实现的,所以有必要借助一个通用的配置管理机制,通常使用配置服务器来管理配置。
Spring Cloud Config
Spring Cloud Config 为分布式系统的外部配置提供了服务端和客户端的支持方案。在配置的服务端您可以在所有环境中为应用程序管理外部属性的中心位置。客户端和服务端概念上的Spring Environment
和 PropertySource
抽象保持同步, 它们非常适合Spring应用程序,但是可以与任何语言中运行的应用程序一起使用。当应用程序在部署管道中从一个开发到测试直至进入生产时,您可以管理这些环境之间的配置,并确保应用程序在迁移时具有它们需要运行的所有内容。服务器存储后端的默认实现使用git,因此它很容易支持标记版本的配置环境,并且能够被管理内容的各种工具访问。很容易添加替代的实现,并用Spring配置将它们插入。
Spring Cloud Config 包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。Spring cloud使用git或svn存放配置文件,默认情况下使用git,我们先以git为例做一套示例。
springcloud-config-repo(远程git配置仓库)
我这里先在 我的scexample GitHub仓库创建远程配置存储仓库springcloud-config-repo。并且创建了3个远程配置文件。
#开发使用远程云配置
springcloud-config-dev.yml
#生产使用远程云配置
springcloud-config-pro.yml
#测试使用远程云配置
springcloud-config-test.yml
配置信息分别为
springcloud-config-dev.yml
writer: jason(cry)
springcloud-config-pro.yml
writer: jason(silent)
springcloud-config-test.yml
writer: jason(smile)
config-server(配置服务端)
我们新建一个子moudle->config-server
pom.xml
在pom.xml中添加spring-cloud-config-server依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>scexample</artifactId>
<groupId>com.pubutech</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>config-server</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
resources目录下新建application.yml配置文件,配置信息如下:
server:
port: 8888
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/Jaysong2012/scexample # 配置git仓库的地址
search-paths: springcloud-config-repo # git仓库地址下的相对地址,可以配置多个,用,分割。
username: # git仓库的账号(私有库必填)
password: # git仓库的密码(私有库必填)
label: master #配置git仓库的分支
这里需要注意:
Spring Cloud Config也提供本地存储配置的方式。我们只需要设置属性spring.profiles.active=native
,Config Server会默认从应用的src/main/resource目录下检索配置文件。也可以通过spring.cloud.config.server.native.searchLocations=file:/properties/
属性来指定配置文件的位置。虽然Spring Cloud Config提供了这样的功能,但是为了支持更好的管理内容和版本控制的功能,还是推荐使用git的方式。
ConfigServerApplication.java
新建Spring BootApplication ConfigServerApplication
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
//开启配置服务器
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
启动测试
访问http://localhost:8888/springcloud-config/pro/master
结果如下:
{
"name":"springcloud-config",
"profiles":[
"pro"
],
"label":"master",
"version":"a669f6077492e5988bc21a3a3da2eaead7578469",
"state":null,
"propertySources":[
{
"name":"https://github.com/Jaysong2012/scexample/springcloud-config-repo/springcloud-config-pro.yml",
"source":{
"writer":"jason(silent)"
}
}
]
}
我们成功的读取了远程的配置文件
继续访问http://localhost:8888/master/springcloud-config-pro.yml
我们可以直接拿到整个配置信息。
http请求地址和资源文件映射规则如下:
/{name}/{profile}[/{label}]
/{name}-{profile}.yml
/{label}/{name}-{profile}.yml
/{name}-{profile}.properties
/{label}/{name}-{profile}.properties
通过这里和上面返回的json结果,我们不难看出来
- name : 对应profile的配置名称前缀(也理解为application的配置前缀)
- profile:对应application的配置profile
- label:对应远程仓库的分支
config-client(读取远程配置的客户端)
我们新建一个子moudle->config-client
pom.xml
修改pom.xml添加spring-cloud-starter-config依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>scexample</artifactId>
<groupId>com.pubutech</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>config-client</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml
resources目录下新建application.yml本配置
server:
port: 8889
spring:
application:
name: config-client
bootstrap.yml
resources目录下新建bootstrap.yml远程配置
spring:
cloud:
config:
name: springcloud-config #对应{application}部分
profile: pro #对应{profile}部分
uri: http://localhost:8888/ #配置中心的具体地址
label: master #对应git的分支。如果配置中心使用的是本地存储,则该参数无用
discovery:
service-id: config-server #指定配置中心的service-id,便于扩展为高可用配置集群。
ConfigClientApplication.java
新建启动SpringBoot Application
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
新建测试加载远程配置的案例Controller
@RestController
public class ConfigClientController {
@Value("${writer}")
String writer;
@RequestMapping(value = "/writer")
public String writer(){
return writer;
}
}
启动测试
访问http://localhost:8889/writer