一、概述:
RabbitMQ的安装参考:https://blog.csdn.net/qq_45173404/article/details/116429302
Spring Cloud Bus中文参考文档:https://www.springcloud.cc/spring-cloud-bus.html
一、原理简介
Spring Cloud Bus用轻量级消息代理链接分布式系统的节点。然后可以使用该代理传播状态更改(例如配置更改)或其他管理指令。一个关键思想是,bus(总线)就像扩展的Spring Boot应用程序的分布式执行器。然而,它也可以用作应用程序之间的沟通渠道。这个项目提供了一个AMQP代理或Kafka作为传输的启动器。
通常会使用消息代理来构建一个主题,然后把微服务架构中的所有服务都连接到这个主题上去,当我们向该主题发送消息时,所有订阅该主题的服务都会收到消息并进行消费。
使用 Spring Cloud Bus 可以方便地构建起这套机制,所以 Spring Cloud Bus 又被称为消息总线。
其中bus的意思:公共汽车,总线的意思。计算机科学中是总线的意思。
通俗的说:
Spring Cloud Bus集成了市面上常见的RabbitMQ和Kafka等消息代理。其会连接微服务系统中所有拥有Bus总线机制的节点,当有数据变更的时候,会通过消息中间件使用消息广播的方式通知所有的微服务节点同步更新数据。(如:微服务配置更新等)
就和我们生活中的广播 电台一样/或者带天线的电视机一样,当我们订阅了一个主题,即收听了这个电台或者卫视台,那么当电视台领导向电视台发送一个节目内容时,我们正在观看或者收(即订阅)该频道的都会收到 那个节目消息。
Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。
目前 Spring Cloud Bus 支持两种消息代理:RabbitMQ 和 Kafka。
原理图:
以下是官网文档:
使用:
如果Spring Cloud Bus在类路径上检测到自己,那么它通过添加Spring Boot自动配置来工作。要启用总线,请将spring-cloud-starter-bus-amqp或spring-cloud-starter-bus-kafka添加到依赖管理中。剩下的由spring cloud来安排。请确保代理(RabbitMQ或Kafka)可用并已配置。在本地主机上运行时,您不需要做任何事情。如果您远程运行,使用Spring Cloud Connectors或Spring Boot约定来定义代理凭证,如下面的Rabbit示例所示:
远程运行要使用RabbitMQ:
总线目前支持将消息发送到侦听的所有节点或特定服务的所有节点(由Eureka定义)。/bus/*执行器名称空间有一些HTTP端点。目前,实施了两项。第一个是/bus/env,它发送键/值对来更新每个节点的Spring环境。第二个,/bus/refresh,重新加载每个应用程序的配置,就好像它们都在其/refresh端点上被ping通了一样。
注意:
Springcloud总线启动器包括RabbitMQ和Kafka,因为这是两个最常见的实现。然而,Spring Cloud Stream非常灵活,并且他的绑定器与Spring - Cloud -bus一起工作。
总线端点:
Spring Cloud Bus提供两个端点/actuator/busrefresh 和/actuator/busenv,分别对应Spring Cloud Commons中的/actuator/refresh 和/actuator/env。
2.1.总线刷新端点
/actuator/busrefresh端点清除RefreshScope缓存并重新绑定@ConfigurationProperties。
要暴露/actuator/busrefresh端点(就好像我们收音机或者手机要暴露天线一样,这样才能接收消息),您需要向您的应用程序添加以下配置:
management.endpoints.web.exposure.include=busrefresh
2.2.总线Env端点:
/actuator/busenv端点跨多个实例使用指定的键/值对更新每个实例环境。
要暴露/actuator/busenv端点,需要在应用程序中添加以下配置:
management.endpoints.web.exposure.include=busenv
3.处理一个实例:
应用程序的每个实例都有一个服务ID,它的值可以用spring.cloud.bus.id设置,它的值应该是一个由冒号分隔的标识符列表,顺序从最不特定到最特定。id默认值从环境构造为spring.application.name和server.port的组合(或通过spring.application.index来设置)。
HTTP端点接受“目的地”参数,例如“/busrefresh/customers:9000”,其中目的地是ApplicationContext ID。如果ID由Bus上的一个实例拥有,那么它将处理消息,所有其他实例将忽略它。
4.寻址服务的所有实例:
在Spring PathMatcher(路径分隔符为冒号:)中使用“destination”参数来确定实例是否处理该消息。使用上面的示例,“/busrefresh/customers:**”将定位“客户”服务的所有实例,而不管配置文件和端口设置为ApplicationContext ID。
5.应用程序上下文ID必须唯一
我们一般通过 spring.application.name+server.port来组合成唯一的id
6.自定义Message Broker:
Spring Cloud Bus使用Spring Cloud Stream来广播消息。因此,要使消息进入流,只需要在类路径中包含您所选择的绑定器实现。使用AMQP (RabbitMQ)和Kafka (spring-cloud-start -bus-[AMQP | Kafka])可以方便地启动总线。一般来说,Spring Cloud Stream依赖于Spring Boot自动配置约定来配置中间件。例如,可以使用spring.rabbitmq修改AMQP代理地址。配置属性。Spring Cloud Bus在Spring . Cloud . Bus中有几个本机配置属性。(例如,spring.cloud.bus.destination是要用作外部中间件的主题名称)。通常,默认值就足够了。
7.追踪Bus事件:
总线事件(RemoteApplicationEvent的子类)可以通过设置spring.cloud.bus.trace.enabled=true来跟踪。如果您这样做,Spring Boot TraceRepository(如果它存在)将显示每个发送的事件和每个服务实例的所有acks。下面的例子来自/trace端点:
前面的跟踪显示从customers:9000发送了RefreshRemoteApplicationEvent,广播到所有服务,并由customers:9000和stores:8081接收(ack)。
要处理ack信号,您可以向您的应用添加AckRemoteApplicationEvent和SentApplicationEvent类型的@EventListener(并启用跟踪)。或者您可以利用TraceRepository并从中挖掘数据。
注意:
任何Bus应用程序都可以跟踪ack,但有时在一个可以对数据进行更复杂查询的中央服务器中这样做是有用的。或将其转发到专门的跟踪服务。
8.广播自己的事件
总线可以携带任何类型的RemoteApplicationEvent事件。默认传输是JSON,反序列化器需要提前知道要使用哪些类型。要注册一个新类型,必须将其放到org.springframework.cloud.bus.event的子包中。
要自定义事件名称,您可以在自定义类上使用@JsonTypeName,或者依赖默认策略,即使用类的简单名称。
9配置属性:
二、动态刷新的全局广播:
(1)建模块:cloud-config-client-3366
(2)改pom:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<!--config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--eureka-client 注册中心 client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--springboot-web 两个组件-->
<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>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency><!--热部署-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
(3)写bootstrap.yml:
server:
port: 3366
spring:
application:
name: config-client
cloud:
config: #config 客户端配置
label: master #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称,也可以换成test文件
uri: http://localhost:3344 #配置中心地址
#rabbitmq相关配置
rabbitmq:
host: 192.168.211.211
port: 5672
username: admin
password: 123
#eureka注册中心配置
eureka:
client:
service-url:
defaultZone: http://eureka7003.com:7003/eureka
#暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
(4)主启动类:com.fan.springcloud.ConfigClientMain3366
package com.fan.springcloud;
import com.netflix.discovery.EurekaNamespace;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3366 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3366.class,args);
}
}
(5)3366新客户端的controller:controller.ConfigClientController
@RestController
@Slf4j
@RefreshScope //动态刷新同步的
public class ConfigClientController {
@Value("${server.port}")
private String serverPort;
@Value("${config.info}")
private String configInfo;
@GetMapping(value = "/configInfo")
public String configInfo(){
return "serverPort:"+serverPort +"\t\n--configinfo:"+configInfo;
}
}
具体步骤:
方式一:
方式2:由广播中心通知其他微服务
3344配置中心 广播通知 其他客户端
3344 配置总控 修改添加的pom:bus-amqp:
<!--bus-amqp-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
3344 配置总控 修改yml:修改2处
server:
port: 3344 #消费端 ,建议一定有
spring:
application:
name: cloud-config-center #微服务名称,建议有
cloud:
config:
server:
git:
uri: https://gitee.com/fandongdong666/springcloud-config.git #github上git仓库克隆地址
username: fandongdong666 # your ysername
password: fan18729985349 #your password
search-paths: #github上的搜索路径,即仓库名
- springcloud-config
label: master #读取的分支
#rabbitmq相关配置
rabbitmq:
host: 192.168.211.211
port: 5672
username: admin
password: 123
eureka: #注册中心
client:
register-with-eureka: true #true表示向注册中心注册自己。
fetch-registry: true #true要抓取/拉取注册信息。
service-url: # 将自己注册到 哪些默认注册中心 中去(localhost:7003)
defaultZone: http://eureka7003.com:7003/eureka
#暴露监控端点
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
修改3355 和3366:这两个微服务的都是bootstrap.yml
pom添加消息总线支持:bus-amqp
注意:微服务的id必须唯一:
总线尝试两次来消除对事件的处理—一次来自原始的ApplicationEvent,一次来自队列。为此,它根据当前服务ID检查发送服务ID。如果一个服务的多个实例具有相同的ID,则不处理事件。在本地机器上运行时,每个服务位于不同的端口上,该端口是ID(服务名+端口号组成了唯一id)的一部分。Cloud Foundry提供了一个index来区分。为了确保ID在Cloud Foundry之外是唯一的,将spring.application.index设置为每个服务实例的唯一值。
Spring Cloud Bus使用Spring Cloud Stream来广播消息。因此,要使消息进入流,只需要在类路径中包含您所选择的绑定器实现。使用AMQP (RabbitMQ)和Kafka (spring-cloud-start -bus-[AMQP | Kafka])可以方便地启动总线。一般来说,Spring Cloud Stream依赖于Spring Boot自动配置约定来配置中间件。例如,可以使用spring.rabbitmq修改AMQP代理地址。*配置属性。Spring Cloud Bus在Spring . Cloud . Bus中有几个本机配置属性
启动服务开始测试:eureka,3344,3355,3366
开始测试,查看注册的微服务:http://localhost:7003/
配置中心的网页测试:config-3344.com:3344/config-dev.yml
客户端网页测试:
http://localhost:3355/configInfo
http://localhost:3366/configInfo
然后发送post请求后再次测试:
在windows控制台发送以下请求:(win键+r–>输入cmd -->输入以下内容即可)
curl -X POST “http://localhost:3344/actuator/bus-refresh”
三、动态刷新的定点通知:
HTTP端点接受一个“目的地”路径参数,例如/busrefresh/customers:9000,其中destination是一个服务ID。如果该ID属于总线上的一个实例,则该实例处理消息,而所有其他实例都忽略它。
先在git上修改文件,然后刷新总控(即发送post请求)3344,这时候刷新的时候需要指定到某个具体的微服务,如:
curl -X POST “http://localhost:3344/actuator/bus-refresh/config-client:3355”
注意:config-client:3355 是微服务的名称+端口号
测试结果:
四、总结bus消息总线全局广播:
-
总控微服务需要添加的内容:
1.1 总控微服务的pom添加spring-cloud-starter-bus-amqp依赖
1.2 总控微服务的yml添加rabbitmq配置和暴露监控端点的management.endpoints. web.exposure.include : 'bus-refresh’配置。 -
配置的客户端 需要添加的内容:
2.1 pom添加spring-cloud-starter-bus-amqp依赖
2.2 bootstrap.yml添加rabbitmq配置和暴露监控端点的management.endpoints. web.exposure.include : “*”
2.3 controller添加@RefreshScope 动态刷新的注解