Spring Boot应用最大的特点就是使用配置来代替编码,很多时候启用某一个功能只需要引入相关的starter,再加入对应的配置项就可以了,例如数据源,安全性,中间件等等。对于单个项目,我们一般会把配置项放到application.property或者application.yaml中,在不同的环境中替换相应的配置值就可以了。但在Spring Cloud项目中,因为引入微服务概念,导致整个系统的服务实例会大大增加,这样如果系统新增了一个配置项,还像以前那样逐个去手工替换配置文件,运维人员估计要累到吐血。而且传统的方式还有一个问题,替换配置文件以后必须要重启整个服务,这对于部分应用来说也是不可接受的。
我们之前在介绍Consul的时候,提到了Consul除了提供服务的注册/发现功能以外,还提供了key/value的存储功能,而且Consul可以提供对存储键值对的CP(强一致性,类似于zookeeper)保证,这样我们就可以利用Consul来实现统一配置中心的相关功能了( Spring Cloud Config 组件也提供基于GIT或SVN的配置中心解决方案)。Spring Cloud 已经为Consul配置中心提供相关的实现框架 — spring-cloud-starter-consul-config。我们只需要在每个服务模块中加入相关的依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
然后在resources目录中新增一个配置文件bootstrap.yml,用于配置远程配置中心的相关信息:
spring:cloud:consul:host: 192.168.1.220port: 8500discovery:prefer-ip-address: trueconfig:enabled: trueprefix: configdefault-context: applicationprofile-separator: ','data-key: dataformat: yaml
这个bootstrap.yml是spring boot的引导配置文件,其加载优先级高于其它任何配置,是在一个独立的父级上下文(Bootstrap Context)中加载解析的。与配置中心相关的配置都应该放到该配置文件之中,才能够实现初始化应用程序之前先到配置中心去抓取必要的配置。spring.cloud.consul.config的相关配置项意义如下:
enabled: 是否启用consul配置中心
prefix: 配置项在consul中的根目录,默认是config
default-context: 所有服务的公共配置所在的配置目录,默认是application
profile-separator: 配置项目录中profile名称的分隔符,默认是 “,”
data-key:配置项的key名称,默认是data
format:配置项的值的文件格式
比如按照以上的配置,如果spring.application.name设置为order-service,spring.profiles.active为dev的服务启动后默认会去consul的key/value目录的以下四个位置去查找配置信息,配置的key为data,值必须为yaml格式:
config/application,dev/:公共配置信息,profile为dev
config/application/:公共配置信息
config/order-service,dev/:order-service服务的专属配置信息,profile为dev
config/order-service/:order-service服务的专属配置信息
现在我们在order-service服务上测试一下,首先在consul的config/application/和config/order-service/目录分别加入两个配置项:
然后添加一个测试的ConfigController ,测试配置项的注入:
@RestController
@RequestMapping("/api/config")
@Slf4j
public class ConfigController {@Value("${global-config.key1}")private String key1;@Value("${service-config.key2}")private String key2;@GetMapping("/test-config-center")public void testConfigCenter() {log.info("global-config.key1:{},service-config.key2:{}", key1, key2);}}
-----------------------------------
springcloud配置文件加载顺序 spring profile active springcloud配置中心consul
https://blog.51cto.com/u_16099298/10397150
访问 http://localhost:9001/api/config/test-config-center 就可以看到控制台输出了对应的配置值:
2020-04-27 11:18:19.505 INFO 15828 --- [nio-9001-exec-9] c.g.d.s.o.controller.Controller : global-config.key1:value1,service-config.key2:value2
我们再来测试一下配置项的动态更新。为了支持动态更新配置参数,我们需要在注入参数的Spring Component上加入一个@RefreshScope注解,这样才能在参数更新后刷新当前的scope:
@RestController
@RequestMapping("/api/config")
@Slf4j
@RefreshScope
public class ConfigController
然后在consul ui中修改配置项的值,将global-config.key1的值修改为:modified-value,保存后再次访问http://localhost:9001/api/config/test-config-center,可以看到控制台打印出的属性值已经是我们修改后的最新的结果了:
2020-04-27 11:45:01.978 INFO 16368 --- [TaskScheduler-1] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-config/order-service/'}, BootstrapPropertySource {name='bootstrapProperties-config/application/'}]
LOGBACK: No context given for c.q.l.core.rolling.SizeAndTimeBasedRollingPolicy@2107186835
2020-04-27 11:45:01.992 INFO 16368 --- [TaskScheduler-1] o.s.boot.SpringApplication : No active profile set, falling back to default profiles: default
2020-04-27 11:45:02.009 INFO 16368 --- [TaskScheduler-1] o.s.boot.SpringApplication : Started application in 0.694 seconds (JVM running for 70.244)
2020-04-27 11:45:02.150 INFO 16368 --- [TaskScheduler-1] o.s.c.e.event.RefreshEventListener : Refresh keys changed: [global-config.key1]
2020-04-27 11:45:14.614 INFO 16368 --- [io-9001-exec-10] c.g.d.s.o.controller.ConfigController : global-config.key1:modified-value,service-config.key2:value2
-----------------------------------
springcloud配置文件加载顺序 spring profile active springcloud配置中心consul
https://blog.51cto.com/u_16099298/10397150
其实配置项的动态刷新是通过不断的轮询Consul的HTTP API,检测相关的配置目录是否发生了变化来实现的,轮询的间隔时间可以通过spring.cloud.consul.config.watch.delay来配置,默认是1000毫秒,如果不想启用自动刷新机制,可以配置spring.cloud.consul.config.watch.enabled=false
本文的相关代码可以查看这里GitHub - davidfantasy/spring-cloud-demo: spring cloud技术体系的实例代码