1. 概述

本文将深入探讨 Spring Cloud Bus 项目。Spring Cloud Bus 通过轻量级消息代理连接分布式系统节点,主要用于广播配置变更或其他管理指令。可以将其视为分布式版的 Actuator

该项目默认使用 AMQP 代理作为传输层,但也可替换为 Apache Kafka 或 Redis(目前仅支持这三种传输方式)。本教程将以 RabbitMQ 为主要传输层进行演示,请确保已提前启动 RabbitMQ 服务。

2. 前置准备

开始前建议先完成《Spring Cloud Configuration 快速入门》教程。我们将基于现有的配置服务器和客户端进行扩展,实现配置变更的自动通知机制。

2.1. RabbitMQ 安装

推荐使用 Docker 方式部署 RabbitMQ,操作非常简单。首先确保已安装 Docker,然后执行以下命令:

docker pull rabbitmq:3-management

此命令会拉取预装管理插件的 RabbitMQ 镜像。接着启动容器:

docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management

启动后访问 http://localhost:15672 可进入管理控制台(默认账号密码均为 guest)。同时 RabbitMQ 会在 5672 端口监听消息。

3. 为配置客户端添加 Actuator

假设已有配置服务器和客户端在运行。目前每次配置变更后都需要重启客户端——这显然不够优雅。

先停止客户端,在 ConfigClient 控制器类上添加 @RefreshScope 注解:

@SpringBootApplication
@RestController
@RefreshScope
public class SpringCloudConfigClientApplication {
    // 代码实现...
}

然后更新 pom.xml 添加 Actuator 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

最新版本可查看 Maven 中央仓库

默认情况下 Actuator 的敏感接口(包括 /refresh)是受保护的。为简化演示,在 application.yml 中关闭安全验证:

management:
  security:
    enabled: false

⚠️ 注意:Spring Boot 2 后 Actuator 接口默认不暴露,需额外配置:

management:
  endpoints:
    web:
      exposure:
        include: "*"

重启客户端后,在 GitHub 仓库中将 user.roleDeveloper 改为 Programmer。此时配置服务器会立即更新,但客户端不会。手动触发刷新只需向 /actuator/refresh 发送空 POST 请求:

$> curl -X POST http://localhost:8080/actuator/refresh

返回的 JSON 会显示更新的属性:

[
  "user.role"
]

验证更新结果:

$> curl http://localhost:8080/whoami/Mr_Pink
Hello Mr_Pink! You are a(n) Programmer and your password is 'd3v3L'.

✅ 成功通过 /refresh 接口实现无重启配置更新。

4. Spring Cloud Bus 集成

虽然 Actuator 能刷新单个客户端,但在云环境中逐个触发显然不现实。Spring Cloud Bus 正是解决这个问题的利器。

4.1. 客户端改造

让客户端订阅 RabbitMQ 消息队列,添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
    <version>4.1.1</version>
</dependency>

最新版本查看 Maven 中央仓库

application.yml 中配置 RabbitMQ 并启用 Bus:

---
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
  cloud:
    bus:
      enabled: true
      refresh:
        enabled: true

⚠️ 生产环境务必修改默认账号密码!

改造后客户端新增 /bus-refresh 接口,调用该接口会:

  1. 从配置服务器获取最新配置,更新 @RefreshScope 标注的 Bean
  2. 向 AMQP 交换机发送刷新事件消息
  3. 所有订阅节点同步更新配置

4.2. 服务器改造

在配置服务器添加两个依赖实现自动化:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-monitor</artifactId>
    <version>4.1.1</version>
</dependency>

最新版本查看 Maven 中央仓库

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    <version>4.1.1</version>
</dependency>

最新版本查看 Maven 中央仓库

application.properties 中添加 RabbitMQ 配置:

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

4.3. GitHub Webhook 配置

现在配置服务器已能通过 RabbitMQ 广播变更事件,但如何感知配置文件修改?需要配置 GitHub Webhook:

  1. 进入配置仓库的 GitHub 页面
  2. 选择 Settings → Webhooks
  3. 点击 Add webhook
  4. Payload URL 填写配置服务器的 /monitor 接口地址:
    http://root:s3cr3t@REMOTE_IP:8888/monitor
    
  5. Content type 选择 application/json
  6. Secret 留空
  7. 点击 Add webhook 完成配置

5. 功能测试

确保所有服务运行中。当前客户端显示:

$> curl http://localhost:8080/whoami/Mr_Pink
Hello Mr_Pink! You are a(n) Programmer and your password is 'd3v3L'.

现在修改 GitHub 仓库中的配置文件,将 user.role 改回 Developer

user.role=Developer

无需手动刷新,立即检查客户端:

$> curl http://localhost:8080/whoami/Mr_Pink
Hello Mr_Pink! You are a(n) Developer and your password is 'd3v3L'.

✅ 客户端自动同步更新!在 GitHub Webhook 的 Recent Deliveries 中可查看发送给配置服务器的 JSON 数据。服务器日志会显示:

o.s.cloud.bus.event.RefreshListener: Received remote refresh request. Keys refreshed []

6. 总结

本文基于现有 Spring Cloud 配置服务器和客户端:

  1. 通过 Actuator 实现手动配置刷新
  2. 集成 Spring Cloud Bus 实现配置变更广播
  3. 配合 GitHub Webhook 实现全自动更新流程

完整代码示例可在 GitHub 仓库 获取。踩坑提示:生产环境务必注意 RabbitMQ 安全配置,避免使用默认凭证!


原始标题:Spring Cloud Bus