前言
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
咱们书接上文,在上一章中我们简单的聊了聊SpringCloud的配置中心(大聪明教你学Spring Cloud核心组件 | 第四篇:配置中心(Config)),说完了配置中心以后,可能会有一些小伙伴产生了疑问:那如果我有一百个项目的话,修改一次配置文件岂不是要请求一百次刷新地址?那这时候我们就该有请SpringCloud中的消息总线(Spring Cloud Bus)闪亮登场了。
什么是SpringCloud Bus
首先还是先简单说说什么是Spring Cloud Bus。
Spring cloud bus通过轻量消息代理连接各个分布的节点。会用在广播状态的变化(例如配置变化)或者其他的消息指令。Spring bus的一个核心思想是通过分布式的启动器对spring boot应用进行扩展,也可以用来建立一个多个应用之间的通信频道。目前唯一实现的方式是用AMQP消息代理作为通道。
大家可以将它理解为管理和传播所有分布式项目中的消息既可,其实本质是利用了MQ的广播机制在分布式的系统中传播消息,目前常用的有Kafka和RabbitMQ。
那么在本文中,我们选择使用Kafka(搭建启动kafka的步骤百度上有很多,这里就不再多说了),通过Kafka来讲解一下如合使用Spring Cloud Bus实现广播配置文件的变化。
整合SpringCloud Bus
我们打开上一节中搭建的两个项目,分别是config-serve和config-client,然后对他们进行一个小小的改造。
首先修改一下config-serve项目,我们需要在它的pom.xml文件中增加几个依赖,pom.xml如下所示:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springboot</groupId>
<artifactId>config-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-server</name>
<description>Demo project for springboot config</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
<!--SpingBoot 服务监控 帮助你在应用程序生产环境时监视和管理应用程序。可以使用HTTP的各种请求来监管,审计,收集应用的运行情况-->
<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>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
然后我们再修改一下application.yml配置文件,我们需要在application.yml中增加一些关于kafka的相关设置
server:
port: 8012
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://gitee.com/trs_sjz/springcloud-config
username: XXXXXX
password: XXXXXX
basedir: D:\springcloudconfig\gitee
search-paths: config-cloud
# kafka
stream:
kafka:
binder:
brokers: localhost:9092 #kafka地址
zk-nodes: localhost:2181 #zookeeper地址
auto-create-topics: true
bus:
trace:
enabled: true
enabled: true
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
# 客户端调用需要
management:
endpoints:
web:
exposure:
include: bus-refresh
security:
enabled: false
同样的,我们也要对config-client进行相同的改造,下面直接贴代码
pom.xml文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springboot</groupId>
<artifactId>config-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>config-client</name>
<description>Demo project for config-client</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring cloud config 客户端包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml文件
server:
port: 3302
management:
endpoints:
web:
exposure:
include: bus-refresh
data:
env: NaN
user:
username: NaN
password: NaN
bootstrap.yml文件
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8081/eureka/
spring:
profiles:
active: dev
---
spring:
profiles: prod
application:
name: ziye
cloud:
config:
uri: http://localhost:8012
label: master
profile: prod
# kafka
stream:
kafka:
binder:
brokers: localhost:9092
zk-nodes: localhost:2181
auto-create-topics: true
bus:
trace:
enabled: true
---
spring:
profiles: dev
application:
name: ziye
cloud:
config:
uri: http://localhost:8012
label: master
profile: dev
# kafka
stream:
kafka:
binder:
brokers: localhost:9092
zk-nodes: localhost:2181
auto-create-topics: true
bus:
trace:
enabled: true
为了模拟多个项目,我们再复制一个config-client2项目(config-client2与config-client的配置相同,config-client2所用端口为3303),然后我们分别启动config-client、config-client2、config-server以及Eureka-Server服务注册中心 ==(千万别忘了启动kafka)==。
项目启动成功后,我们首先来访问一下http://localhost:8012/ziye-dev.yml和http://localhost:8012/ziye-prod.yml,我们可以看到页面返回了配置文件的内容。
然后我们再去访问一下http://localhost:3302/autoShow和http://localhost:3303/autoShow2地址(为了区分config-client和config-client2,让二者请求不同的配置文件,config-client请求ziye-dev.yml,config-client2请求ziye-prod.yml)。
我们可以看到页面也正常返回了配置文件中的信息。
那么接下来我们对gitee上的配置文件进行一个小小的修改,修改后我们可以直接刷新上面提到的四个地址,这时候我们会发现通过config-server请求的两个地址所展示的信息已经被更新了,变成了修改后的配置信息;而通过http://localhost:3302/autoShow和http://localhost:3303/autoShow2请求所展示的配置信息并没有更新。
此时我们就需要请求一下http://localhost:8012/actuator/bus-refresh地址来刷新一下了,==这里需要注意的是请求一定是POST请求(可以通过Postman来进行请求)==
P.S. 如果我们不希望刷新全部客户端的话,我们可以用下面的方式进行刷新http://localhost:8012/actuator/bus-refresh/客户端名:客户端口号(端口号可用*来代替)
请求成功后,我们再分别访问一下http://localhost:3302/autoShow和http://localhost:3303/autoShow2地址,我们就发现此时获取到了最新的配置文件信息。
有了上面的讲解,我相信各位小伙伴应该能很快的理解下面这张图了
根据此图我们可以很容易的总结出利用Spring Cloud Bus做配置更新的步骤:
- 提交代码触发post给客户端A发送/actuator/bus-refresh
- 客户端A接收到请求从Server端更新配置并且发送给Spring Cloud Bus
- Spring Cloud bus接到消息并通知给其它客户端
- 其它客户端接收到通知,请求Server端获取最新配置
- 全部客户端均获取到最新的配置
结语
微服务一般都采用集群方式部署,而且在高并发下经常需要对服务进行扩容、缩容、上线、下线的操作。比如我们需要更新配置,又或者需要同时失效所有服务器上的某个缓存,需要向所有相关的服务器发送命令,此时就可以选择使用Spring Cloud Bus了。其实说的再简单点就是,在我们需要把一个操作散发到所有后端相关服务器的时候,我们的首选就是Spring Cloud Bus ,借用一句广告语来说就是:自从用了消息总线,我的腰不疼了,腿不痛了,一口气管理一千个服务也不费劲了。
本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇
希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)
如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。
爱你所爱 行你所行 听从你心 无问东西