- `bus` 简介
- `bus` 工作架构
- `bus` 消息总线的实现
- `config` 配置中心服务端
- `Maven` 添加依赖
- `application.properties` 配置文件
- `config` 配置中心客户端
- `Maven` 添加依赖
- 远程 `git` 仓库配置文件
- `eureka-client-consumer`
- `eureka-client-producer`
- 添加 `@RefreshScope` 注解
- `/bus-refresh` 接口
- 测试
- 测试一
- 测试二
- 测试三
从 上一篇 文章可以得知 config client 服务从 config server 端获取自己对应的配置文件,但是目前的问题是:当远程 git 仓库配置文件发生改变时,每次都是需要重启 config client 服务,如果有上百上千个微服务呢? 我想我们不会一个个去重启每个微服务,也就是说如何让 config server 端通知到 config client 端? 即 config client 端如何感知到配置发生更新?
这时候就该 bus 上场了,使用 springcloud bus(国人很形象的翻译为消息总线)可以完美解决这一问题
bus 工作架构大家可以将它理解为管理和传播所有分布式项目中的消息既可,其实本质是利用了 MQ 的广播机制在分布式的系统中传播消息,目前常用的有 Kafka 和 RabbitMQ 。利用 bus 的机制可以做很多的事情,其中配置中心客户端刷新就是典型的应用场景之一,我们用一张图来描述 bus 在配置中心使用的机制
- 提交配置触发 post 请求给 server 端的 bus/refresh 接口
- server 端接收到请求并发送给 springcloud bus 总线
- springcloud bus 接到消息并通知给其它连接到总线的客户端
- 其它客户端接收到通知,请求 server 端获取最新配置
- 全部客户端均获取到最新的配置
它的特点:config 配置中心 server 端承担起配置刷新的职责
bus 消息总线的实现项目结构依然使用上一篇的,如下
config 配置中心服务端 Maven 添加依赖application.properties 配置文件org.springframework.cloud spring-cloud-starter-bus-amqp
完整配置如下,主要增加了 rabbitmq 的配置与健康检查
server.port=8070 #注册进eureka的名称 spring.application.name=eureka-client-config eureka.client.service-url.defaultZone=http://eureka7001:8761/eureka/ eureka.instance.prefer-ip-address=true #gitee的仓库地址 spring.cloud.config.server.git.uri=https://gitee.com/chaojiangcj/springcloud-learn-config.git spring.cloud.config.server.git.username=chaojiangcj@yeah.net spring.cloud.config.server.git.password=123456789abc #配置仓库需要找的文件路径 spring.cloud.config.server.git.search-paths=eureka-client-* spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest #健康检查 management.endpoints.web.exposure.include=*config 配置中心客户端 Maven 添加依赖
eureka-client-consumer,eureka-client-producer 两个项目都要引入
远程 git 仓库配置文件 eureka-client-consumerorg.springframework.cloud spring-cloud-starter-bus-amqp org.springframework.boot spring-boot-starter-actuator
完整配置如下,增加了 rabbitmq 的配置
spring.profiles.active=dev server.port=8090 #注册进eureka的名称 spring.application.name=eureka-client-consumer eureka.client.service-url.defaultZone=http://eureka7001:8761/eureka/ eureka.instance.prefer-ip-address=true #Feign默认整合了Hystrix,要想为Feign打开Hystrix支持,需要此项设置 #在springcloud Dalston之前的版本中,Feign默认开启Hystrix支持,无需设置feign.hystrix.enabled=true #从springcloud Dalston版本开始,Feign的Hystrix支持默认关闭,需要手动设置开启 feign.hystrix.enabled=true #配ribbon的超时时间,默认二者都是1000 #ribbon.ConnectTimeout=2000 #ribbon.ReadTimeout=2000 #第一次启动时,请求接口查询数据库有点耗时,会进入降级策略,所以将hystrix的超时时间设置为3s,默认是1s,这是全局设置 hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000 spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest #自定义配置,用于测试 congfig.version=config-version 0.2eureka-client-producer
完整配置如下,增加了 rabbitmq 的配置
server.port=8080 #注册进eureka的名称 spring.application.name=eureka-client-producer #JDBC 配置 spring.datasource.druid.url=jdbc:mysql://127.0.0.1:3306/shiro?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC spring.datasource.druid.username=root spring.datasource.druid.password=123456 spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #druid 连接池配置 spring.datasource.druid.initial-size=3 spring.datasource.druid.min-idle=3 spring.datasource.druid.max-active=10 spring.datasource.druid.max-wait=60000 #指定 mapper 文件路径 mybatis.mapper-locations=classpath:org/example/mapper/*.xml mybatis.configuration.cache-enabled=true #开启驼峰命名 mybatis.configuration.map-underscore-to-camel-case=true #打印 SQL 语句 mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl eureka.client.service-url.defaultZone=http://eureka7001:8761/eureka/ eureka.instance.prefer-ip-address=true spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=guest spring.rabbitmq.password=guest添加 @RefreshScope 注解
该注解我们添加在 eureka-client-consumer 项目的 controller 层,增加了一个测试接口,如下
@RefreshScope
@Slf4j
@Controller
@RequestMapping(path = "/UserConsumer")
public class UserConsumerController {
@Autowired
private UserConsumerService userConsumerService;
@Value(value = "${congfig.version}")
private String configVersion;
@GetMapping(path = "/findOneById")
@ResponseBody
public ResultVo findOneById(Integer id) {
return userConsumerService.findOneById(id);
}
@GetMapping(path = "/queryOneById")
@ResponseBody
public ResultVo queryOneById(@RequestParam(name = "id") Integer id) {
return userConsumerService.queryOneById(id);
}
@GetMapping(path = "/getConfigVersion")
@ResponseBody
public String getConfigVersion() {
log.info("configVersion的值为:" + configVersion);
return configVersion;
}
}
- 自动刷新只能刷新 @RefreshScope 注解下的配置,一些特殊配置,如数据库等,需要同样先设置数据库链接 ConfigServer 类,然后通过加 @RefreshScope 注解方式自动刷新
要实现配置自动刷新,需要调用 /bus-refresh 接口通知 config server 端,有两种方式
- 手动调用(post 请求):http://ip:port/actuator/bus-refresh (config server 端地址)
- 配置 git 的 webhook,当 git 端配置发生改变,自动调用 /bus-refresh 接口
分别启动 rabbitmq,eureka-client-consumer,eureka-client-producer,eureka-client-config 以及 eureka 的服务端项目
测试一启动上述服务之后,首先来请求接口 http://127.0.0.1:8090/UserConsumer/getConfigVersion 获取这个变量
测试二修改变量如下
再次请求接口 http://127.0.0.1:8090/UserConsumer/getConfigVersion 获取这个变量,如下
- 首先请求接口 http://127.0.0.1:8070/actuator/bus-refresh(config 服务端的 ip,port),注意是 post 请求方式。它什么都没有返回
- 这里看看请求 http://127.0.0.1:8070/actuator 接口,它返回了健康监控的一些信息,如下
- 再一次请求接口 http://127.0.0.1:8090/UserConsumer/getConfigVersion 获取这个变量,如下
- 同时,看 rabbitmq 的管理页面,创建的交换机如下
创建的队列如下



