7–SpringCloud搭建消息总线

  先回顾一下,在之前的Spring Cloud Config的介绍中,我们还留了一个悬念:如何实现对配置信息的实时更新。虽然,我们已经能够通过/refresh接口和Git仓库的Web Hook来实现Git仓库中的内容修改触发应用程序的属性更新。但是,若所有触发操作均需要我们手工去维护Web Hook中的应用位置的话,这随着系统的不断扩张,会变的越来越难以维护,而消息代理中间件是解决该问题最为合适的方案。是否还记得我们在介绍消息代理中的特点时有提到过这样一个功能:消息代理中间件可以将消息路由到一个或多个目的地。利用这个功能,我们就能完美的解决该问题,下面我们来说说Spring Cloud Bus中的具体实现方案。

RabbitMQ实现

准备工作

   这里我们不做新的应用,但需要用到上一章中,我们已经实现的关于Spring Cloud Config的几个工程,若读者对其还不了解,建议先阅读

  5–SpringCloud搭建分布式配置中心

  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属性。
  • 接着,我们修改5--SpringCloud--Config/ghghspace-dev.properties中的from属性值,并发送POST请求到其中的一个/bus/refresh
  • 最后,我们再分别访问启动的两个config-client的/from请求,此时这两个请求都会返回最新的5--SpringCloud--Config/ghghspace-dev.properties中的from属性。

  到这里,我们已经能够通过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搭建消息总线