Spring Cloud Config 统一配置中心java
一般,咱们会使用配置文件来管理应用的配置。如一个 Spring Boot 的应用,能够将配置信息放在 application.yml 文件中,若是须要多环境配置,能够设置多个 application-{profile}.yml,再经过 spring.profiles.active={profile} 来实现多环境的切换。这样的管理对于单体应用或者说划分的服务很少的状况下没什么问题,但若是是一个微服务架构的应用系统有着不少个微服务,集中管理配置就很是必要了git
对于这样的配置管理,咱们会但愿它github
Spring Cloud Config 为分布式系统外部化配置提供了服务器端和客户端的支持,分为 Config Server 和 Config Clientspring
Config Server 是用来集中管理应用程序的各个环境下的配置,默认是使用 Git 来存储配置内容的,能够很方便的对配置实现版本管理(也支持 Subversion 和本地化文件系统存储)json
Config Client 即用来获取 Config Server 中存储的配置内容bootstrap
建立一个 Spring Boot 工程,maven 添加 spring-cloud-config-server
服务器
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.SR1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
在程序启动类上添加注解 @EnableConfigServer
,开启配置服务器的功能架构
@SpringBootApplication @EnableConfigServer public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
Config Server 默认是使用 Git 来存储配置内容的,下面来配置下 git 仓库的相关信息app
application.ymlmaven
server: port: 8888 spring: application: name: config-server cloud: config: server: git: # git 仓库地址 uri: https://github.com/Morgan412/weixin-order # 仓库下的搜索路径 search-paths: conf # git仓库帐号 username: # git仓库密码 password:
若是是公开仓库能够不用帐号和密码,在仓库的 conf/
目录下创建以下的配置文件
每一个文件中分别填入以下配置内容
Config Server 的端点
使用 Config Server 的端点能够获取配置文件的内容,请求地址与配置文件的映射以下:
上面的地址均可以映射到 {application}-{profile}.properties/yml
配置文件,{label}
表示对应 Git 仓库的分支,默认是 master
启动上面的 config-server 项目,经过 url 访问远程 Git 仓库 master 分支下 conf 目录下的 product-dev.yml
配置文件内容
经过 http://localhost:8888/product/dev 访问,能够得到应用名称、profile、git label、git version、配置文件URL、配置内容等信息
{ "name": "product", "profiles": [ "dev" ], "label": null, "version": "052661b72043aad390e6774666b5594d6e0ba116", "state": null, "propertySources": [ { "name": "https://github.com/Morgan412/weixin-order/conf/product-dev.yml", "source": { "profile": "dev" } }, { "name": "https://github.com/Morgan412/weixin-order/conf/product.yml", "source": { "profile": "default" } } ] }
而 http://localhost:8888/product-dev.yml 和 http://localhost:8888/product-dev.properties 只会获取到配置文件中的属性,包括 {application}.yml/properties
中的属性
上面建立了一个 Config Server 来集中管理配置,那下面来配置 Config Client 让微服务获取配置信息
一样是建立一个 Spring Boot 工程,添加 Config Client 的依赖,这里省略了其余依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
相关配置以下
server: port: 8082 spring: application: # 对应 config server 所获取的配置文件 {application} name: product cloud: config: # 指定 config server 的地址,默认是 http://localhost:8888 uri: http://localhost:8888 # 对应配置文件的 {profile} profile: dev # 分支 label: master
上面的配置能够从 /{application}/{profile}/{label}
获取对应 config server 中的配置文件中的属性,其中
另外这些均可以经过设置 spring.cloud.config.*
(*
为 name
、profile
、label
) 来覆盖
若是这时就启动该服务,就可能会出现一些问题,由于上面关于 config client 的配置须要放到 bootstrap.yml
而不是 application.yml
。
咱们来想一个问题,咱们交给 config server 集中管理的配置内容是否是本来应该放在 application.yml
中在程序启动的时候被加载的,而如今咱们把获取配置内容的 config client 相关配置放在了 application.yml
中,这样是否是就有点不对了,由于这里会出现一个前后顺序的问题。若是咱们把配置放在了 application.yml
中,那么它会先去加载 bootstrap.yml
的配置属性(若是没有,会加载默认配置),假如咱们在 application.yml
中配置的 uri 端口是 8080,那么它将不会被应用,仍是默认的 8888 端口
Spring Cloud 有一个 引导上下文 的概念,它是主应用程序的父上下文,这个引导上下文负责从外部源(配置服务器,如Config Server)加载配置属性,及解密外部配置文件中的属性。主应用程序加载的是 application.(properties/yml) 中的属性,引导上下文加载 bootstrap.(properties/yml) 中的属性。这两个上下文共享一个
Environment
,但配置在 boostrap.* 中的属性有更高的优先级,所以默认状况下不能被本地配置覆盖。设置
spring.cloud.bootstrap.enabled=false
能够禁用引导过程
能够来写个 Controller 来测试一下获取配置
@RestController class ConfigClientController { @Value("${profile}") private String profile; @RequestMapping("/profile") public String getProfile() { return this.profile; } }