7--SpringCloud搭建消息总线
先回顾一下,在之前的Spring Cloud Config的介绍中,我们还留了一个悬念:如何实现对配置信息的实时更新。虽然,我们已经能够通过/refresh
接口和Git仓库的Web Hook来实现Git仓库中的内容修改触发应用程序的属性更新。但是,若所有触发操作均需要我们手工去维护Web Hook中的应用位置的话,这随着系统的不断扩张,会变的越来越难以维护,而消息代理中间件是解决该问题最为合适的方案。是否还记得我们在介绍消息代理中的特点时有提到过这样一个功能:消息代理中间件可以将消息路由到一个或多个目的地。利用这个功能,我们就能完美的解决该问题,下面我们来说说Spring Cloud Bus中的具体实现方案。
RabbitMQ实现
准备工作
这里我们不做新的应用,但需要用到上一章中,我们已经实现的关于Spring Cloud Config的几个工程,若读者对其还不了解,建议先阅读
6--SpringCloud搭建分布式配置中心(续-高可用性)
config-eurekaServer:服务注册中心
config-server:配置了Git仓库,并注册到了Eureka的服务端。
config-client:通过Eureka发现Config Server的客户端,应用名为ghghspace,用来访问配置服务器以获取配置信息。该应用中提供了一个/from
接口,它会获取5--SpringCloud--Config /ghghspace-dev.properties
中的from属性返回。
在本地安装好RabbitMQ服务;
扩展config-client应用
修改pom.xml
增加spring-cloud-starter-bus-amqp
模块
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
在配置文件中增加关于RabbitMQ的连接和用户信息
server.port=7002 #对应前配置文件中的{application}部分 spring.application.name=ghghspace eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/ #参数设置为true,开启通过服务来访问Config Server的功能 spring.cloud.config.discovery.enabled=true #指定配置中心的实例名 spring.cloud.config.discovery.serviceId=config-server #对应前配置文件中的{profile}部分 spring.cloud.config.profile=dev #对应前配置文件的git分支 spring.cloud.config.label=master #mq链接信息 spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.username=gh spring.rabbitmq.password=123456
启动config-server,再启动两个config-client(分别在不同的端口上,比如7002、7003),我们可以在config-client-eureka中的控制台中看到如下内容,在启动时候,客户端程序多了一个/bus/refresh
请求。
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)
- 先访问两个config-client的
/from
请求,会返回当前的from属性。 - 接着,我们修改
中的from属性值,并发送POST请求到其中的一个5--SpringCloud--Config
/ghghspace-dev.properties/bus/refresh
。 - 最后,我们再分别访问启动的两个config-client的
/from
请求,此时这两个请求都会返回最新的
中的from属性。5--SpringCloud--Config
/ghghspace-dev.properties
到这里,我们已经能够通过Spring Cloud Bus来实时更新总线上的属性配置了。
原理分析
我们通过使用Spring Cloud Bus与Spring Cloud Config的整合,并以RabbitMQ作为消息代理,实现了应用配置的动态更新。
整个方案的架构如上图所示,其中包含了Git仓库、Config Server、以及微服务“Service A”的三个实例,这三个实例中都引入了Spring Cloud Bus,所以他们都连接到了RabbitMQ的消息总线上。
当我们将系统启动起来之后,“Service A”的三个实例会请求Config Server以获取配置信息,Config Server根据应用配置的规则从Git仓库中获取配置信息并返回。
此时,若我们需要修改“Service A”的属性。首先,通过Git管理工具去仓库中修改对应的属性值,但是这个修改并不会触发“Service A”实例的属性更新。我们向“Service A”的实例3发送POST请求,访问/bus/refresh
接口。此时,“Service A”的实例3就会将刷新请求发送到消息总线中,该消息事件会被“Service A”的实例1和实例2从总线中获取到,并重新从Config Server中获取他们的配置信息,从而实现配置信息的动态更新。
而从Git仓库中配置的修改到发起/bus/refresh
的POST请求这一步可以通过Git仓库的Web Hook来自动触发。由于所有连接到消息总线上的应用都会接受到更新请求,所以在Web Hook中就不需要维护所有节点内容来进行更新,从而解决了通过Web Hook来逐个进行刷新的问题。
源码下载:7--SpringCloud搭建消息总线