博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Config Server——使用Spring Cloud Bus自动刷新配置
阅读量:7024 次
发布时间:2019-06-28

本文共 3361 字,大约阅读时间需要 11 分钟。

前文我们讨论了使用/refresh 端点手动刷新配置,但是如果所有微服务节点的配置都需要手动去刷新的话,那必然是一个繁琐的工作,并且随着系统的不断扩张,会变得越来越难以维护。因此,实现配置的自动刷新是很有必要的,本节我们讨论使用Spring Cloud Bus实现配置的自动刷新。

Spring Cloud Bus提供了批量刷新配置的机制,它使用轻量级的消息代理(例如RabbitMQ、Kafka等)连接分布式系统的节点,这样就可以通过Spring Cloud Bus广播配置的变化或者其他的管理指令。使用Spring Cloud Bus后的架构如图9-2所示。

9-2.png

图9-2 使用Spring Cloud Bus的架构图

由图可知,微服务A的所有实例通过消息总线连接到了一起,每个实例都会订阅配置更新事件。当其中一个微服务节点的/bus/refresh端点被请求时,该实例就会向消息总线发送一个配置更新事件,其他实例获得该事件后也会更新配置。

下面我们以RabbitMQ为例,为大家讲解如何使用Spring Cloud Bus实现配置的自动刷新。

(1) 安装RabbitMQ。RabbitMQ的安装非常简单,本书不再赘述。

(2) 复制项目microservice-config-client-refresh ,将ArtifactId修改为microservice-config-client-refresh-cloud-bus

(3) 为项目添加spring-cloud-starter-bus-amqp 的依赖。

org.springframework.cloud
spring-cloud-starter-bus-amqp

(4) 在bootstrap.yml中添加以下内容:

spring:  rabbitmq:    host: localhost    port: 5672    username: guest    password: guest

这样代码就改造完成了。

测试

(1) 启动microservice-config-server

(2) 启动microservice-config-client-refresh-cloud-bus,可发现此时控制台打印类似于以下的内容:

[           main] o.s.b.a.e.mvc.EndpointHandlerMapping     : Mapped "{[/bus/refresh],methods=[POST]}" onto public void org.springframework.cloud.bus.endpoint.RefreshBusEndpoint.refresh(java.lang.String)

说明此时有一个/bus/refresh 端点。

(3) 将microservice-config-client-refresh-cloud-bus的端口改成8082,再启动一个节点。

(4) 访问 ,可获得结果:dev-1.0。

(4) 将git仓库中的microservice-foo-dev.properties文件内容改为profile=dev-1.0-bus

(5) 发送POST请求到其中一个Config Client节点的的/bus/refresh端点,例如:

curl -X POST http://localhost:8081/bus/refresh

(6) 访问两个Config Client节点的/profile端点,会发现两个节点都会返回dev-1.0-bus ,说明配置内容已被刷新。

借助Git仓库的WebHook,我们就可轻松实现配置的自动刷新。如图9-3所示。

9-3.png

图9-3 Git WebHooks设置

局部刷新

某些场景下(例如灰度发布),我们可能只想刷新部分微服务的配置,此时可通过/bus/refresh端点的destination参数来定位要刷新的应用程序。

例如:/bus/refresh?destination=customers:9000 ,这样消息总线上的微服务实例就会根据destination参数的值来判断是否需要要刷新。其中,customers:9000 指的是各个微服务的ApplicationContext ID。

destination参数也可以用来定位特定的微服务。例如:/bus/refresh?destination=customers:** ,这样就可以触发customers微服务所有实例的配置刷新。

扩展阅读:关于ApplicationContext ID

默认情况下,ApplicationContext ID是spring.application.name:server.port,详见org.springframework.boot.context.ContextIdApplicationContextInitializer.getApplicationId(ConfigurableEnvironment) 方法。

架构改进

在前面的示例中,我们通过请求某个微服务的/bus/refresh端点的方式来实现配置刷新,但这种方式并不优雅。原因如下:

(1) 打破了微服务的职责单一性。微服务本身是业务模块,它本不应该承担配置刷新的职责。

(2) 破坏了微服务各节点的对等性。

(3) 有一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就不得不修改WebHook的配置。

我们不妨改进一下我们的架构。

9-4.png

图9-4 使用Spring Cloud Bus的架构图

如图9-4,我们将Config Server也加入到消息总线中,并使用Config Server的/bus/refresh端点来实现配置的刷新。这样,各个微服务只需要关注自身的业务,而不再承担配置刷新的职责。代码详见microservice-config-server-refresh-cloud-bus

跟踪总线事件

一些场景下,我们可能希望知道Spring Cloud Bus事件传播的细节。此时,我们可以跟踪总线事件(RemoteApplicationEvent的子类都是总线事件)。

跟踪总线事件非常简单,只需设置spring.cloud.bus.trace.enabled=true ,这样在/bus/refresh端点被请求后,访问/trace端点就可获得类似如下的结果:

{  "timestamp": 1481098786017,  "info": {    "signal": "spring.cloud.bus.ack",    "event": "RefreshRemoteApplicationEvent",    "id": "66d172e0-e770-4349-baf7-0210af62ea8d",    "origin": "microservice-foo:8081",    "destination": "**"  }},{  "timestamp": 1481098779073,  "info": {    "signal": "spring.cloud.bus.sent",    "type": "RefreshRemoteApplicationEvent",    "id": "66d172e0-e770-4349-baf7-0210af62ea8d",    "origin": "microservice-config-server:8080",    "destination": "**:**"  }}...

这样,我们就可清晰地知道事件的传播细节。

本文链接:

**版权声明: **本博客由创作,采用 许可协议。可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。

你可能感兴趣的文章
【UWP应用开发实战】第二弹 移动版秒变桌面版 实践:罗马数计算器
查看>>
Java IO 之 FileInputStream & FileOutputStream源码分析
查看>>
时序列数据库武斗大会之什么是 TSDB ?
查看>>
fork() and vfork() getppid's result
查看>>
线程的其他特征
查看>>
《PostgreSQL 权威指南》Request For Comments - 结构
查看>>
【JSP开发】一个防盗链的WEB小例子
查看>>
我遇见的哪些 CSS 中有趣的尺寸、宽高
查看>>
域名分配问题
查看>>
VUE缓存:动态keep-alive
查看>>
杂项记录薄
查看>>
python 元类
查看>>
怎么让代码不再臃肿,写的像诗一样优雅
查看>>
移动端如果没有meta标签的viewport
查看>>
前端面试题
查看>>
WebSocket原理及技术简介
查看>>
自定义控件 --- 电池icon
查看>>
嘻哈说:设计模式之工厂方法模式
查看>>
JS原生Ajax基本操作
查看>>
JS == 操作符的隐式转换,翻译ecma-262/5.1/#sec-11.6.1
查看>>