springCloud(20):统一管理微服务配置-刷新配置
一、使用/refresh端点手动刷新配置
很多场景下,需要在运行期间动态调整配置。如果配置发生了修改,微服务要如何实现配置的刷新呢?
1、复制config-client,重命名为config-client-refresh(端口:5021)
2、添加actuator依赖的jar
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
3、在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; } }
4、测试
a、访问http://localhost:5021/profile,获得结果:dev-1.0
b、修改git仓库的spring-cloud-demo-dev.yml文件内容为:profile: dev-1.0-update
c、重新访问http://localhost:5021/profile,获得结果:dev-1.0,说明配置还没有更新
d、POST请求http://localhost:5021/refresh
e、再次访问http://localhost:5021/profile,获得结果:dev-1.0-update,说明配置已经刷新
二、使用Spring Cloud Bus自动刷新配置
2.1、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.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、测试
1、依次启动config-server、config-client-refresh-cloud-bus、config-client-refresh-cloud-bus-2。
2、访问http://localhost:5021/profile,获取结果:dev-1.0-update
3、修改git仓库的spring-cloud-demo-dev.yml文件内容为:profile: dev-1.0-update222
4、POST请求http://localhost:5021/bus/refresh刷新配置
5、访问http://localhost:5021/profile与http://localhost:5022/profile,获取结果:dev-1.0-update222,说明配置内容已被刷新
补充:使用Git仓库的WebHooks,就可以轻松实现配置的自动刷新。
2.3、局部刷新
某些场景下,如只想刷新部分微服务的配置,可通过/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.4、架构改进
通过请求某个微服务的/bus/refresh端点的方式来实现配置的刷新的方式并不优雅,原因如下:
1、破坏了微服务的职责单一原则。业务微服务只应关注自身业务,不应该承担配置刷新的职责。
2、破坏了微服务各节点的对等性。
3、有一定的局限性。如:微服务在迁移时,网络地址常常会发送变化,此时如果想自动刷新配置,就不得不修改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.5、跟踪总线事件
一些场景下如果希望知道Spring cloud Bus事件传播的细节,可以跟踪总线事件(Re-moteApplicationEvent的子类都是总线事件)。
想要跟踪总线事件非常简单,只须设置spring.cloud.bus.trace.enabled=true,这个在/bus/refresh端点被请求后,访问/trace端点就可获得类似如下的结果:
转载于:https://blog.51cto.com/1754966750/1961920