Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持。使用Config Server,您可以在所有环境中管理应用程序的外部属性。客户端和服务器上的概念映射与Spring Environment和PropertySource抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用。随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。很容易添加替代实现,并使用Spring配置将其插入。
1、概述
1.1 分布式系统面临的–配置文件问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务,由于每个服务都需要必要的配置信息才能运行,所以一套集中式的,动态的配置管理设施是必不可少的。spring cloud提供了configServer来解决这个问题,我们每一个微服务自己带着一个application.yml,那上百个的配置文件修改起来,令人头疼!
1.2 什么是SpringCloud config分布式配置中心?
SpringCloud Config 为微服务架构中的微服务提供集中化的外部支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置。
SpringCloud Config 分为服务端和客户端两部分。
服务端也称为 分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理。并且可用通过git客户端工具来方便的管理和访问配置内容。
1.3 SpringCloud Config 分布式配置中心能干嘛?
- 集中式管理配置文件
- 不同环境,不同配置,动态化的配置更新,分环境部署,比如 /dev /test /prod /beta /release
- 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
- 当配置发生变动时,服务不需要重启,即可感知到配置的变化,并应用新的配置
- 将配置信息以REST接口的形式暴露
1.4 SpringCloud Config 分布式配置中心与GitHub整合
由于SpringCloud Config 默认使用git来存储配置文件 (也有其他方式,比如自持SVN 和本地文件),但是最推荐的还是git ,而且使用的是 http / https 访问的形式。
2、入门案例
2.1 环境搭建
去gitee新建一个远程配置中心仓库
将远程仓库clone到本地,并新建application.yml文件
填入以下内容,并上传到远程仓库
更新到远程仓库
2.2 SpringCloud Config服务端实现
创建server模块:springcould-config-server-3344,导入依赖
<dependencies>
<!--config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>
编写配置文件
#设置微服务运行端口
server:
port: 3344
#标识微服务名称
spring:
application:
name: springcould-config-server
#连接远程仓库的配置
cloud:
config:
server:
git:
uri: https://gitee.com/ilovemo/springcloud-config.git
#直接去远程仓库上复制地址,注意使用的是HTTPS,不再是使用git本地克隆的时候使用的SSH,原因就是正常分布式中微服务连接都是基于HTTP的
#注意是URI不是URL
编写主启动类,注意使用注解@EnableConfigServer 开启config配置服务端
@SpringBootApplication
@EnableConfigServer //开启config配置服务端
public class ConfigServer_3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigServer_3344.class, args);
}
}
这里直接启动会报错,需要加NativeEnvironmentRepository的Bean,再config包下新建ConfigBean.java配置类
@Configuration
public class ConfigBean {
@Bean
public NativeEnvironmentRepository
nativeEnvironmentRepository(NativeEnvironmentRepositoryFactory factory,
NativeEnvironmentProperties environmentProperties) {
return factory.build(environmentProperties);
}
}
测试
直接访问application.yml报错,这是因为我们准备了两套环境,需要指定获取哪套环境
官方文档指出,除了使用上面例子中的URL获取到仓库中配置文件,还可以使用其他的形式获取到配置文件资源
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
可见不同的访问URL得到的数据资源格式不一样,数据也有一些不一样
2.3 SpringCloud Config 客户端实现
客户端就是服务提供者对应的微服务模块,在spring cloud config中,客户端需要从spring cloud config服务端获取配置文件的信息
在本地仓库中创建一个新的yml配置文件,作为等会儿写的服务提供者的远程配置文件
spring:
profiles:
active: dev
---
#端口配置
server:
prot: 8201
#spring配置
spring:
profiles: dev
application:
name: springcould-provider-dept
#eureka配置
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
---
#端口配置
server:
prot: 8202
#spring配置
spring:
profiles: test
application:
name: springcould-provider-dept
#eureka配置
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
推送到远程仓库
创建一个新的子model:springcould-config-client-3355,导入依赖
<dependencies>
<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>
</dependencies>
创建配置文件,这里我们需要学习一个新的配置文件:bootstrap.yml,原来我们创建的都是application.yml,那么这两个配置文件有什么区别呢?
- bootstrap.yml:代表系统级别的配置
- application.yml:代表应用级别的配置
- 在原来学习反射的时候,我们学习了类加载器,其中有3个类加载器
- 根类加载器(bootstrap class loader)
- 扩展类加载器(extensions class loader)
- 系统类加载器(system class loader)
- 其中根加载器的优先级别最高
- 类比学习,bootstrap.yml配置文件的优先级应该比application.yml配置文件的优先级高
为什么要搞一个系统配置文件呢?原因就是application.yml中的配置可能和远程仓库中的配置冲突,就会造成配置不能正常的使用,而我们使用bootstrap.yml由于优先级别更高,那么最终配置就会按照bootstrap.yml中的配置为准,可以防止本地和远程仓库中的配置冲突问题
在spring cloud config中,只有config服务器模块才去连接远程仓库,而config客户端只应该去连接config服务器,所以config客户端的config.uri属性值应该是config服务端的地址(IP+端口)
spring:
cloud:
config:
uri: http://localhost:3344 #连接config服务端
config客户端除了要配置config.uri之外,还需要配置自己需要加载远程仓库中的哪一个配置文件,按照刚刚直接通过config服务器获取配置文件的URL,我们需要配置name(配置文件名称)、profile(这个配置文件中的哪一个环境下的配置)、label(配置文件所在分支)、uri(config服务端的地址[IP+端口])
# 系统级别的配置
spring:
cloud:
config:
name: config-client # 需要从git上读取的资源名称,不要后缀
profile: test
label: master
uri: http://localhost:3344
编写入口程序
@SpringBootApplication
public class ConfigClient_3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClient_3355.class,args);
}
}
注意:入口程序并不需要加什么注解,按照正常的spring boot的入口程序写就行了
编写一个controller,用来检测config客户端模块是不是能够读取远程的配置文件并作为自己模块配置文件的一部分进行使用
@RestController
public class ConfigController {
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-url.defaultZone}")
private String eurekaServer;
@Value("${server.port}")
private String serverPort;
@RequestMapping("/getConfig")
public String getConfig() {
return "applicationName = " + this.applicationName + "\n" +
"eurekaServer = " + this.eurekaServer + "\n" +
"serverPort = " + this.serverPort;
}
}
在上面的controller中,我们使用了注解@Value,用于直接向成员属性中注入指定的值,我们又使用了${ }来解析一些的远程配置文件中才配置了的一些配置变量的值,最后通过controller的一个API向外提供输出服务,我们可以直接访问这个API,来检验config客户端是不是读取到了远程仓库中指定配置文件的内容