SpringBoot 项目一般将一些重要的参数配置在application.yml或者application.properites中,譬如外部服务链接、数据库地址及帐号信息、某些业务变量。随着业务的开展,实现一个完整的业务流程一般须要开发并管理多个微服务,一旦这些参数调整,须要修改多个微服务的配置并重启,这将给运维及生产带来额外的工做和影响。为了解决这个问题,咱们能够将这些配置抽取到一个公共的地方,可参照另外一篇文章“Spring Cloud 微服务公共配置处理请添加连接描述”,将微服务的公共配置抽取出来。完成抽取只是第一步,一旦数据库的帐号或者外部服务链接修改,服务仍是须要逐个重启,如何解决这个问题呢?git
Spring Cloud的message和integration机制,容许咱们经过cloud bus,将变动通知到每个服务,实现动态刷新,其架构设计以下(摘自网络)web
实现这个过程,须要引入spring cloud的相关组件:注册服务、消息服务、集成服务、配置服务等,以及一个可用的消息队列。下面我将以Springboot2.1.8,cloud版本Greenwich.SR3为例,介绍如何实现。spring
服务清单数据库
Eureka服务比较简单,配置和启动效果以下。bootstrap
server: port: 7777 eureka: instance: hostname: localhost client: register-with-eureka: false fetch-registry: false service-url: default-zone: http://${eureka.instance.hostname}:${server.port}/eureka/
Configserver须要引入bus-amqp,pom配置以下:浏览器
boot相关springboot
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-context</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-bus</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-monitor</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream</artifactId> </dependency>
application的配置以下,网络
spring config相关:架构
management的配置是为了支持bus-fresh,rabbitmq须要同时配置在bootstrap和application中。app
主要包括eureka配置,rabbitmq配置及用来测试ext.key。configclient02的配置和01几乎一致,仅端口和应用名称不一样。
因此服务启动后,能够看到eureka的管理界面以下:
内容分别以下:
ext.key=hello client 111
ext.key=hello client 222
这个时候就能够测试了。测试方式能够经过浏览器访问configserver,直接请求配置文件,也能够经过程序测试,先说经过浏览器访问。
springboot项目启动时,若是引入了config-client和context包,则会自动根据bootstrap指定的地址获取配置,请求方式以下:
http://${spring.cloud.config.uri}/${spring.cloud.config.name}/<spring.cloud.config.profile>/<lspring.cloud.config.label>;, 参照bootstrap.yml的定义。
这个项目直接请求:http://localhost:8021/cfg_client01/dev/aliyun_dev, 返回以下:
这种请求方式,也是springboot项目启动时初始化的请求方式。
下面以更实际的方式测试,在controller中引用一个变量,ext.key, 查看属性的变化。
@RestController @RequestMapping("/test") @RefreshScope public class IndexController { @Value("${ext.key}") private String key; @GetMapping("/key") public String printKey() { return key; } }
controller很简单,惟一须要注意的是,必定要加上@RefreshScope,由于spring在刷新时,会基于这个注解,肯定要不要刷新bean或者方法内的引用属性。
第一次直接请求:
如今修改git上的配置文件,将ext.key改为111000和222000。
这个时候就能够调用spring的bus-refresh了。调用refresh的时候,能够直接调用server的,也能够调用某个具体的client,我但愿一次刷新,全部的变动都生效,因此直接调用configserver的bus-refresh。固然,也有人将git的commit配置成hookurl,但这种方式在生产环境会有些风险,咱们的作法是,配置文件修改并确认提交后,手动执行一次bus-refrehs。
刷新完成后,分别在请求extkey,查看返回:
能够看到两个应用服务的属性都已经刷新。实现刷新的关键有如下几个:
基于此,咱们就实践了配置文件中属性的动态刷新,实现一次刷新,全部服务生效。这种@Value引用的属性能够这么刷新,那么数据库链接参数呢?下一篇文章,我将介绍如何经过刷新机制,实如今不重启服务的前提下,动态修改数据库的链接参数或者密码。