SpringCloud系列之(十)服务总线
服务总线
一、SpringCloud Bus 消息总线
Bus是对Config的加强
解决的问题:全局通知与定点通知
局域网广播型的通知离不开消息中间件
1. 概述
实现分布式自动刷新配置功能,Spring Cloud Bus配合Spring Cloud Config使用可以实现配置的动态刷新
1.1 是什么
Spring Cloud Bus配合Spring Cloud Config使用可以实现配置的动态刷新。
- Github上的配置更新
- Config Server获取到更新
- Cloud Bus提交刷新配置的POST请求给App A
- a:App A发送消息给Cloud Bus
- a:Cloud Bus广播到其他微服务
Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,
它整合了Java的事件处理机制和消息中间件的功能。
Bus支持两种消息代理:RabbitMQ和Kafka
1.2 能干嘛
Spring Cloud Bus能管理和传播分布式系统间的消息,就像一个分布式执行器, 可用于广播状态更改、事件推送等,也可以当作微服务间的通信通道
1.3 为何被称为总线
什么是总线
在微服务架构的系统中,通常会使用轻量级的消息代理【如:RabbitMQ】来构建一个共用的消息主题【订阅号】, 并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题 上的实例都知道的消息。
基本原理
ConfigClient实例都监听MQ中同一个topic(默认是springCloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到Topic中,这样其它监听同一Topic的服务就能得到通知,然后去更新自身的配置。
https://www.bilbili.com/video/av55976700?from=search&seid=15010075915728605208
一句话总结:SpringCloud与RabbitMQ或Kafka整合完成了事件监听、通知的功能
2. RabbitMQ环境配置
参考Windows 工具使用指南.md 二十八、RabbitMQ
3. SpringCloud Bus动态刷新全局广播
3.1 构建cloud-config-client-3366
-
建Module【cloud-config-client-3366】
-
改POM
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud2020</artifactId> <groupId>com.atguigu.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-config-client-3366</artifactId> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
-
bootstrap.yml
server: port: 3366 spring: application: name: config-client cloud: # Config客户端配置 config: # 分支名称 label: main # 服务名 name: application # 环境 profile: dev # Config服务端地址 uri: http://localhost:3344 # 上述配置含义:加载http://localhost:3344/main/application-dev.yml配置内容到客户端本地 eureka: client: service-url: defaultZone: http://eureka7001.com:7001/eureka management: endpoints: web: exposure: include: "*"
-
主启动
package com.atguigu.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @SpringBootApplication public class ConfigClientMain3366 { public static void main(String[] args) { SpringApplication.run(ConfigClientMain3366.class, args); } }
-
业务类
package com.atguigu.springcloud.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RefreshScope public class ConfigClientController { @Value("${server.port}") private String serverPort; @Value("${config.info}") private String configInfo;
@GetMapping("/configInfo") public String getConfigInfo(){ return "serverPort:"+serverPort+"\t\n\n configInfo: "+configInfo; }
}
3.2 设计思想
从技术角度能够实现的两种设计思想如下:
-
利用消息总线触发一个客户端/bus/refresh,而刷新所有客户端的配置
-
利用消息总线触发一个服务端ConfigServer的/bus/refresh端点,而刷新所有客户端的配置
设计思想选型
第二种设计思想更加合适,第一种设计思想不适合的原因如下
- 打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新职责
- 破坏了微服务各节点的对等性【选中的微服务处于某一业务的微服务集群中的情况下】
- 有一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改
3.3 给cloud-config-center-3344配置中心服务端
添加消息总线支持
-
修改POM,添加如下依赖
<!--添加消息总线RabbitMQ支持--> <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>
-
修改application.yml,添加如下配置
# RabbitMQ相关配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest # 以下配置需要org.springframework.boot.spring-boot-starter-actuator包的支持 # RabbitMQ相关配置,暴露bus刷新配置的端点 management: endpoints: web: exposure: include: 'bus-refresh'
3.4 给cloud-config-center-3355客户端
添加消息总线支持
-
修改POM,添加如下依赖
<!--添加消息总线RabbitMQ支持--> <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>
-
修改bootstrap.yml,添加如下配置
# RabbitMQ相关配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest
3.5 给cloud-config-center-3366客户端
添加消息总线支持
-
修改POM,添加如下依赖
<!--添加消息总线RabbitMQ支持--> <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>
-
修改bootstrap.yml,添加如下配置
# RabbitMQ相关配置 spring: rabbitmq: host: localhost port: 5672 username: guest password: guest
3.6 测试
启动EurekaMain7001
启动cloud-config-center-3344
启动cloud-config-client-3355
启动cloud-config-client-3366
修改Github上配置文件的内容
执行curl -X POST "http://localhost:3344/actuator/bus-refresh"
执行上述命令后,从RabbitMQ的web管理界面能够看到发送了消息
访问http://localhost:3355/configInfo和http://localhost:3366/configInfo,获取配置信息,发现都已经刷新了
至此,实现了SpringCloud Bus动态刷新全局广播
4. SpringCloud Bus动态刷新定点通知
指定具体某一个实例生效而不是全部都生效,不想全部通知,只想定点通知,比如只通知3355,不通知3366
公式:http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}
/bus/refresh请求发给config server并通过destination参数类指定需要更新配置的服务或实例
destination参数的格式为:${spring.application.name}:${server.port}
以修改配置后只更新3355不更新3366为例:
Github上配置文件修改后执行curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"
总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~