一、实现原理
1、ConfigServer(配置中心服务端)从远端git拉取配置文件并在本地git一份,ConfigClient(微服务)从ConfigServer端获取自己对应 配置文件;
2、当远端git仓库配置文件发生改变,ConfigServer如何通知到ConfigClient端,即ConfigClient如何感知到配置发生更新?
Spring Cloud Bus会向外提供一个http接口,即图中的/bus/refresh。我们将这个接口配置到远程的git的webhook上,当git上的文件内容发生变动时,就会自动调用/bus-refresh接口。Bus就会通知config-server,config-server会发布更新消息到消息总线的消息队列中,其他服务订阅到该消息就会信息刷新,从而实现整个微服务进行自动刷新。
二:实现方式
实现方式一:某个微服务承担配置刷新的职责
1、提交配置触发post调用客户端A的bus/refresh接口
2、客户端A接收到请求从Server端更新配置并且发送给Spring Cloud Bus总线
3、Spring Cloud bus接到消息并通知给其它连接在总线上的客户端,所有总线上的客户端均能收到消息
4、其它客户端接收到通知,请求Server端获取最新配置
5、全部客户端均获取到最新的配置
存在问题:
1、打破了微服务的职责单一性。微服务本身是业务模块,它本不应该承担配置刷新的职责。2、破坏了微服务各节点的对等性。3、有一定的局限性。WebHook的配置随着承担刷新配置的微服务节点发生改变。
改进如下方式二:配置中心Server端承担起配置刷新的职责,原理图如下:
1、提交配置触发post请求给server端的bus/refresh接口
2、server端接收到请求并发送给Spring Cloud Bus总线
3、Spring Cloud bus接到消息并通知给其它连接到总线的客户端
4、其它客户端接收到通知,请求Server端获取最新配置
5、全部客户端均获取到最新的配置
第一种配置:
启动rabbitmq
rabbitmq: docker run -d -p 5672:5672 -p 15672:15672 rabbitmq:management
product-service
pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bus-amqp</artifactId> </dependency>
bootstrap.yml
spring: rabbitmq: host: 192.168.180.112 port: 5672 username: guest password: guest #暴露全部的监控信息 management: endpoints: web: exposure: include: "*"
web层
@RestController @RequestScope @RequestMapping("/api/v1/product") public class ProductController { @Value("${server.port}") private String port; @Autowired private ProductService productService; /** * 获取所有商品列表 * @return */ @RequestMapping("list") public Object list(){ return productService.listProduct(); } /** * 根据id查找商品详情 * @param id * @return */ @RequestMapping("find") public Object findById(int id){ // try { // TimeUnit.SECONDS.sleep(2); // } catch (InterruptedException e) { // e.printStackTrace(); // } Product product = productService.findById(id); Product result = new Product(); BeanUtils.copyProperties(product,result); result.setName( result.getName() + " data from port="+port ); return result; } }
测试,要手动发送POST http://localhost:8773/actuator/bus-refresh
就会发现控制台会重新加载配置信息
第二种配置:
其实也是把config-server连到Bus和mq中,然后去请求它,其他服务才进行重新加载。
config-server
pom.xml
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-actuator</artifactId> 4 </dependency> 5 6 <dependency> 7 <groupId>org.springframework.cloud</groupId> 8 <artifactId>spring-cloud-starter-bus-amqp</artifactId> 9 </dependency> 10 <dependency> 11 <groupId>org.springframework.cloud</groupId> 12 <artifactId>spring-cloud-config-server</artifactId> 13 </dependency>
application.yml
#服务名称 spring: application: name: config-server cloud: config: server: git: uri: http://192.168.180.112/root/test.git username: root password: *********** default-label: master rabbitmq: host: 192.168.180.112 username: guest password: guest port: 5672 management: endpoints: web: exposure: include: "*" #服务的端口号 server: port: 9100 #指定注册中心地址 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/
发送请求:http://192.168.137.1:9100/actuator/bus-refresh,会发现所有的服务都会拉取信息。
都会加进队列中。