Bus消息总线

Spring Cloud Bus 配合 Spring Cloud Config 可以实现配置的动态刷新。Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统连接起来的框架,它整合了java的事务处理机制和消息中间件的功能。

Bus支持两种消息代理:RabbitMQ、Kafaka。

Spring Cloud Bus能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当做微服务间的通信通道。

在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他链接在该主题上的实例都知道的消息。

基本原理:ConfigClient实例都监听MQ中同一个topic(默认是springCloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到Topic中,这样其他监听同一个Topic的服务就能得到通知,然后去更新自身的配置。

利用消息总线实现配置的动态刷新

两种方案:

  • 利用消息总线触发一个客户端/bus/refresh,进而刷新所有客户端的配置
  • 利用消息总线触发一个服务端ConfigServer的/bus/refresh的端点,进而刷新所有客户端的配置

不采用方案一的原因:

  • 打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责
  • 破坏了微服务各节点的对等性
  • 有一定的局限性。例如:微服务在迁移时,它的网络地址常常发生变化,此时如果想要做到自动刷新,就会增加更多的修改

服务端的修改:

  1. 添加消息总线依赖
    1. <!-- bus和RabbitMQ -->
    2. <dependency>
    3. <groupId>org.springframework.cloud</groupId>
    4. <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    5. </dependency>
    6. <!-- 因为要暴露端点,还需要引入actuator的依赖 -->
  1. 添加相关配置
    # rabbitmq的相关配置
    spring:
    rabbitmq:
     host: 192.168.29.136
     port: 5672
     username: guest
     password: guest
    # 暴露bus刷新配置的端点
    management:
    endpoints:
     web:
       exposure:
         include: 'bus-refresh'
    

客户端的修改:

  1. 添加消息总线的依赖
    <!-- bus和RabbitMQ -->
    <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    </dependency>
    <!-- 因为要暴露端点,还需要引入actuator的依赖 -->
    
  1. 添加相关配置
    # rabbitmq配置
    spring:
    rabbitmq:
     host: 192.168.29.136
     port: 5672
     username: guest
     password: guest
    # 暴露监控端点
    management:
    endpoints:
     web:
       exposure:
         include: "*"
    

所有模块启动后,如果修改了gitlab上的配置文件,只需要对配置中心的服务端发送一个post请求即可:

curl -X POST "http://localhost:3344/actuator/bus-refresh"

定点通知

Gitlab上的配置修改后,指定具体的某一个实例生效而不是全部。

格式:http://localhost:配置中心端口/actuatoc/bus-refresh/{destination}

/bus/refresh 请求不再发送到具体的服务实例上,而是发给config server,并通过destination参数类指定需要更新配置的服务或实例。

destination的格式:app:index:id

  • app

    指的是:vcap.application.name(如果存在该配置)

或者:spring.application.name

  • index

    指的是:vcap.application.instance_index(如果存在该配置)

或者:spring.application.index

或者:local.server.port

或者:server.port

或者:0(优先级排序号)

  • id

    指的是:vcap.application.instance_id(如果存在该配置)

或者一个随机数。

例如:spring.application.name=cloud-config-client3355、server.port=3355,

则可以发送:curl -X POST "http://localhost:3344/actuator/bus-refresh/cloud-config-client3355:3355"