URI指定配置中心
Spring Cloud Config客户端在启动的时候,默认会从工程的classpath中加载配置信息并启动应用。只有当我们配置spring.cloud.config.uri的时候,客户端才会尝试连接Spring Cloud Config 的服务端来获取远程配置信息并初始化Spring 环境配置。同时,我们必须将该参数配置在bootstrap.properties或者bootstrap.yml、环境变量或是其他优先级高于应用jar包内的配置信息中,才能正确加载到远程配置。若不指定 spring.cloud.config.uri 参数的话,Spring Cloud Config 客户端会默认尝试连接http://localhost:8888。
spring:
application:
name: repo #要获取的应用名
cloud:
config:
uri: http://localhost:5666/ # 配置服务中心的地址
label: master #要获取的分支名
profile: dev #要获取的环境名
服务化配置中心
Config Server 和 Config Client 也能以服务的方式注册到服务中心,通过这种方式还可以实现配置中心的高可用,具体实现参考《Spring Cloud系列(二十九)高可用配置中心—Finchley版本》。
失败快速响应与重试
Spring Cloud Config 的客户端会遇见加载很多其他信息,然后再开始连接Config Server进行属性的注入。当我们构建的应用比较复杂的时候,可能在连接Config Server之前花费较长的启动时间,而在一些特性场景下,我们又希望可以快速知道当前应用是否能顺利地从Config Server获取到配置信息。这对在初期构建调试环境中,可以减少很多等待启动的时间。要实现客户端优先判断Config Sever获取是否正常,并快速响应失败内容,只需要在bootstrap文件中配置参数spring.cloud.config.failFast=true即可。
加上spring.cloud.config.failFast=true后,再启动客户端时,如果Config Server无法正常工作时,会直接报错无法启动。并快速返回失败信息。
java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing
上面演示了当Config Server宕机或者是客户端配置不正确导致连接不到而启动失败的情况,快速响应的配置可以发挥比较好的效果。但是若只是因为网络波动等其他间歇性原因导致的问题,直接启动失败似乎代价太高了。所以,Config 客户端还提供了自动重试的功能,在开启重试功能之前要确保spring.cloud.config.failFast=true。
在客户端的pom.xml中引入spring-retry和spring-boot-starter-aop依赖。
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
不需要做任何配置,启动客户端,在控制台看到如下内容。客户端在连接Config Server失败后,会继续尝试,直到第6次失败后采访错误信息。通过这样的重试机制可以避免一些间歇性问题引起的失败导致客户端应用无法启动的情况。
2018-09-30 10:46:32.409 INFO 13248 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:34.865 INFO 13248 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:36.962 INFO 13248 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:39.555 INFO 13248 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:42.015 INFO 13248 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:44.502 INFO 13248 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.1.228:5666/
2018-09-30 10:46:45.555 ERROR 13248 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing
当然你也可以通过如下参数调整重试次数和重试间隔。
- spring.cloud.config.retry.max-attempts:最大重试次数,默认6次。
- spring.cloud.config.retry.max-interval:最大间隔时间,默认2000毫秒。
- spring.cloud.config.retry.multiplier:初始重试间隔时间,单位毫秒,默认1000毫秒。
- spring.cloud.config.retry.initial-interval:下一间隔的乘数,默认为1.1,所以当最初间隔是1000毫秒时,下一次失败后的间隔为1100毫秒。
获取远程配置
在之前的介绍中,已经对{application}、{profile}、{label}这些参数有了一定的了解。在Git仓库中,一个形如{application}-{profile}.properties或者{application}-{profile}.yml的配置文件,通过URL请求和客户端配置的访问对应可以总结如下:
通过向Config Server发送Get请求以直接的方式获取,可用下面的链接形式。
不带{label}分支信息,默认访问master分支,可使用:
- /{application}-{profile}.properties
- /{application}-{profile}.yml
带{label}分支信息,可使用:
- /{label}/{application}-{profile}.properties
- /{label}/{application}-{profile}.yml
- /{application}/{profile}/{label}
通过客户端配置方式加载的内容如下所示。
- spring.cloud.config.name:对应配置文件中的{application}内容,如果没有配置spring.cloud.config.name则去找spring.application.name。
- spring.cloud.config.profile:对应配置文件中的{profile}内容
- spring.cloud.config.label:对应配置文件中的{label}内容,如不配置默认为master。
spring:
cloud:
config:
name: repo #对应application
uri: http://localhost:5666/ # 配置服务中心的地址
label: master #要获取的分支名
profile: dev #要获取的环境名
动态刷新配置
有时候,我们需要对配置内容做一些实时更新的场景,那么Spring Cloud Config是否可以实现呢?答案显然是可以的。下面,我们看看如何进行改造来实现配置内容的实时更新。
在改造程序之前,我们先将config-server和config-client都启动起来,并访问客户端提供的REST API http://localhost:5777/test1来获取配置信息,可以获得返回内容为:git-dev-1.0-update。接着,我们可以尝试使用Git工具修改当前配置的内容,比如,将config-repo/repo-dev.properties中的form的值从form=git-dev-1.0-update修改为form=git-dev-2.0-update,再访问http://localhost:5777/test1,可以看到其返回内容还是git-dev-1.0-update。
下面,我们将在config-client端增加一些内容和操作以实现配置的刷新:
第一步,在config-client的pom.xml中新增spring-boot-starter-actuator监控模块,其中包含了/actuator/refresh刷新API。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
第二步,暴露refresh端点。
management:
endpoints:
web:
exposure:
include: refresh
这里写"*"报错,说有重复的端点,还没找到原因。
第三步,确认REST Controller添加了@RefreshScope注解
@RefreshScope
@RestController
public class TestController {
。。。
}
重新启动config-client,访问一次http://localhost:5777/test1,可以看到当前的配置值
修改Git仓库config-repo/didispace-dev.properties文件中form的值
再次访问一次http://localhost:5777/test1,可以看到配置值没有改变
通过POST请求发送到http://localhost:5777/actuator/refresh,我们可以看到返回内容如下,代表form参数的配置内容被更新了
[
"form"
]
再次访问一次http://localhost:7002/from,可以看到配置值已经是更新后的值了。
注: @RefreshScope 开启 SpringCloudConfig 客户端的 refresh 刷新范围,来获取服务端的最新配置,@RefreshScope要加在声明@Controller声明的类上,否则refresh之后Conroller拿不到最新的值,会默认调用缓存。
通过上面的介绍,大家不难想到,该功能还可以同Git仓库的Web Hook功能进行关联,当有Git提交变化时,就给对应的配置主机发送/actuator/refresh请求来实现配置信息的实时更新。但是,当我们的系统发展壮大之后,维护这样的刷新清单也将成为一个非常大的负担,而且很容易犯错,那么有什么办法可以解决这个复杂度呢?后续我们将继续介绍如何通过Spring Cloud Bus来实现以消息总线的方式进行通知配置信息的变化,完成集群上的自动化更新。