1、使用/refresh端点手动刷新配置git
不少场景下,须要在运行期间动态调整配置。若是配置发生了修改,微服务要如何实现配置的刷新呢?web
一、复制config-client,重命名为config-client-refresh(端口:5021)spring
二、添加actuator依赖的jarbootstrap
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
三、在Controller上添加@RefreshScope注解,添加@RefreshScope的类会在配置更改时获得特殊的处理网络
package com.liuy.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @description 描述 * @author luis * @version 1.0 * @date:2017年8月29日下午5:54:47 */ @RestController @RefreshScope public class ConfigClientController { @Value("${profile}") private String profile; @GetMapping("/profile") public String hello() { return this.profile; } }
四、测试
架构
a、访问http://localhost:5021/profile,得到结果:dev-1.0app
b、修改git仓库的spring-cloud-demo-dev.yml文件内容为:profile: dev-1.0-update分布式
c、从新访问http://localhost:5021/profile,得到结果:dev-1.0,说明配置还没有更新ide
d、POST请求http://localhost:5021/refreshspring-boot
e、再次访问http://localhost:5021/profile,得到结果:dev-1.0-update,说明配置已经刷新
2、使用Spring Cloud Bus自动刷新配置
2.一、Spring Cloud Bus简介
Spring Cloud Bus使用轻量级的消息代理(如:RabbitMQ/kafaka)链接分布式系统的节点,这样就能够广播状态的更改(如:配置的更新)或者其它的管理指令。可将Spring Cloud Bus想象成一个分布式的Spring Boot Actuator。使用Spring Cloud Bus后的架构以下:
A/B/C客户端都经过消息总线链接到了一块儿,每一个客户端都会订阅配置更新事件。当其中一个微服务节点的/bus/refresh端点被请求时,该客户端就会向消息总线发送一个配置更新事件,其它客户端得到该事件后也会更新配置。
上面说明:
a、提交代码触发post给客户端A发送bus/refresh
b、客户端A接收到请求从Server端更新配置而且发送给Spring Cloud Bus
c、Spring Cloud bus接到消息并通知给其它客户端
d、其它客户端接收到通知,请求Server端获取最新配置
e、所有客户端均获取到最新的配置
2.二、实现自动刷新
a、复制config-client-refresh项目,重命名为config-client-refresh-cloud-bus(端口:5021)
b、添加amqp依赖
<!-- amqp --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
c、修改bootstrap.yml
spring: application: # 对应config Server所获取的配置文件的{application} name: spring-cloud-demo cloud: config: # config Server的地址 uri: http://localhost:5020/ # profile对应config Server所获取的配置文件的{profile} profile: dev # 指定git的分支,对应config Server所获取的配置文件的{label} label: master rabbitmq: host: 192.168.175.13 port: 5672 username: liuy password: 123456
d、复制一份config-client-refresh-cloud-bus,重命名为config-client-refresh-cloud-bus-2(端口:5022)
e、测试
一、依次启动config-server、config-client-refresh-cloud-bus、config-client-refresh-cloud-bus-2。
二、访问http://localhost:5021/profile,获取结果:dev-1.0-update
三、修改git仓库的spring-cloud-demo-dev.yml文件内容为:profile: dev-1.0-update222
四、POST请求http://localhost:5021/bus/refresh刷新配置
五、访问http://localhost:5021/profile与http://localhost:5022/profile,获取结果:dev-1.0-update222,说明配置内容已被刷新
补充:使用Git仓库的WebHooks,就能够轻松实现配置的自动刷新。
2.三、局部刷新
某些场景下,如只想刷新部分微服务的配置,可经过/bus/refresh端点的destination参数来定位要刷新的应用程序。
如:/bus/refresh?destination=customers:9090,这样消息总线上的微服务实例就会根据destination参数的值来判断是否须要刷新。其中customers:9090指的是各个微服务的ApplicationContext ID。
destination参数也能够用来定位特定的微服务。例如:/bus/refresh?destination=customers:**,这样就能够触发customers微服务全部实例的配置刷新。
默认状况下ApplicationContext ID是spring.application.name:server.prot。
2.四、架构改进
经过请求某个微服务的/bus/refresh端点的方式来实现配置的刷新的方式并不优雅,缘由以下:
一、破坏了微服务的职责单一原则。业务微服务只应关注自身业务,不该该承担配置刷新的职责。
二、破坏了微服务各节点的对等性。
三、有必定的局限性。如:微服务在迁移时,网络地址经常会发送变化,此时若是想自动刷新配置,就不得不修改WebHook的配置。
改进:
将Config Server也加入到消息总线中,并使用Config Server的/bus/refresh端点来实现配置的刷新。
Config Server改动:(端口5020)
a、添加依赖
<!-- amqp --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
b、修改application.yml配置
server: port: 5020 #端点的配置 endpoints: sensitive: true shutdown: enabled: true management: security: enabled: false spring: profiles: active: - dev application: name: config-server-refresh-bus cloud: config: server: git: uri: https://git.oschina.net/wadjz/spring-cloud-config.git username: password: rabbitmq: host: 192.168.175.13 port: 5672 username: liuy password: 123456
刷新就能够访问:http://localhost:5020/bus/refresh
2.五、跟踪总线事件
一些场景下若是但愿知道Spring cloud Bus事件传播的细节,能够跟踪总线事件(Re-moteApplicationEvent的子类都是总线事件)。
想要跟踪总线事件很是简单,只须设置spring.cloud.bus.trace.enabled=true,这个在/bus/refresh端点被请求后,访问/trace端点就可得到相似以下的结果: