文章目录
- 1、概述
- ①、工作流程
- ②、什么是总线
- ③、基本原理
- 2、RabbitMQ环境配置
- ①、Windows安装ErLang
- ②、Windows安装RabbitMQ
- ③、安装安装管理工具RabbitMQ-Plugins
- ③、Docker安装
- Ⅰ、拉取镜像
- Ⅱ、运行容器
- Ⅲ、访问web管理页面
- 3、动态刷新全局广播
- ①、创建新的module
- ②、测试
- ③、ConfigServer添加消息总线的支持
- Ⅰ、POM
- Ⅱ、YML
- ④、ConfigClient添加消息总线的支持
- Ⅰ、POM
- Ⅱ、YML
- ⑤、测试
- 4、动态刷新的定点通知
- ①、一个小公式
- ②、测试
1、概述
在学习完
Config
之后,我们发现了一个问题就是每当配置中心配置发生变化以后,都需要将每个微服务重新启动一遍,这样对于某些大型项目而言是很痛苦的,然后我们就又引入了动态刷新功能,每当配置中心配置变化后,我们的运维小哥就手动给每一个微服务都发送一个POST
请求用于更新配置,这样便免于重新启动服务,节约时间,但是这样的动态刷新还是不够彻底,我们如何才能彻底解放运维小哥的双手呢?那就是使用Spring Cloud Bus
配合Spring Cloud Config
使用实现动态刷新配置
Spring Cloud Bus
是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了Java
的事件处理机制和消息中间件的功能,它能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当作微服务间的通信通道,目前支持RabbitMQ
和Kafka
,本文便是使用RabbitMQ
。
①、工作流程
第一种方式(消息发送给一个客户端而刷新所有的配置)
- 配置更新,推送到
Git
仓库 -
Config Server
配置中心同步配置 - 使用订阅了消息的主机给其中一个服务发送一个
Post bus/refresh
更新请求 - 该服务向服务配置中心拉取最新配置,并将信息发送给消息总线
- 这个消息将会通过消息总线广播出去,域内指定或所有服务收到消息就回去服务配置中心拉取最新配置
第二种方式(消息发送给服务配置中心来刷新所有配置)
- 配置更新,推送到
Git
仓库 -
Config Server
配置中心同步配置 - 使用订阅了消息的主机给服务配置中心发送一个
Post bus/refresh
更新请求 - 服务配置中心给消息总线发送通知请求刷新配置
- 消息总线向域内指定或所有服务发送更新通知消息
- 服务从服务配置中心拉取最新配置
相比之下,第二种应该更合理,图一不合理的原因如下
- 打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责。如果这个服务挂了,那是不是就会既影响订单服务,又影响通知服务,数罪并罚死得更惨
- 破坏了微服务各节点的对等性
- 有一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改
②、什么是总线
在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播─些需要让其他连接在该主题上的实例都知道的消息.
③、基本原理
ConfigClient
实例都监听MQ
中同一个topic
(默认是springCloudBus
)。当一个服务刷新数据的时候,它会把这个信息放入到Topic
中,这样其它监听同一Topic
的服务就能得到通知,然后去更新自身的配置。
2、RabbitMQ环境配置
①、Windows安装ErLang
使用
RabbitMQ
时需要下载安装ErLang
环境,因为RabbitMQ
是用ErLang
语言编写的
官网下载速度特别快,所以我这就准备了两种方案
一份云盘链接,提取码:
ppqi
又或者是
RabbitMQ
官网提供的下载链接
傻瓜式安装,就不贴图了,然后配置环境变量(这个不会的还是百度吧)
②、Windows安装RabbitMQ
根据前面下载的
ErLang
版本,选择对应正确的RabbitMQ
版本,根据查阅,这里安装3.8.9
官网下载速度同样不可恭维,可以从华为镜像仓库下载
同样再提供一个云盘链接,提取码:
uput
同样傻瓜式安装,再配置个环境变量
太TM麻烦了
③、安装安装管理工具RabbitMQ-Plugins
进入
RabbitMQ
安装目录下的sbin
目录,打开cmd
,输入
rabbitmq-plugins enable rabbitmq_management
然后点击
RabbitMQ Service - start
如果遇到服务启动失败,报错信息为1067,一般情况都是计算机名为中文,或者安装路径有中文或者其他非法字符,鄙人自以为不会犯这种低级错误,结果导致又查了一个小时,呵呵
如果无误,就会看到以下信息
但是如果你安装完后修改了计算机名称(比如你遇到了我得问题,计算机名为中文,然后改成了英文)即使你启动成功,你还是无法访问
localhost://15672
,网上又查了好一会,得出结论,简单粗暴重装一遍RabbitMQ
。一切就绪,进入管理页面查看,账号密码都是
guest
③、Docker安装
怎么样,Windows
的环境问题搞得是不是头大,按道理实际开发也不会用Windows
的RabbitMQ
啊,所以Docker
才是针不戳
Ⅰ、拉取镜像
#management版本的自带web管理页面
docker pull rabbitmq:3.8.3-management
Ⅱ、运行容器
强调需要映射两个端口一个
5672
,一个15672
,因为RabbitMQ
会开启3
个端口,5672
、15672
、25672
,其中5672
是提供消息队列服务所用,15672
是开启后台http
访问所用,
docker run -d -p 15672:15672 -p 5672:5672 --name myRabbitMQ rabbitmq:3.8.3-management
Ⅲ、访问web管理页面
访问之前记得打开安全组(云服务器)
(拍桌)这TM
比Windows
好用太多了
3、动态刷新全局广播
①、创建新的module
基于上一篇文章,再次创建一个与
3344
相同的3355
,步骤省略,区别仅在于配置文件端口号声明为3366
为了便于区分,两个
ConfigClient
的Controller
修改为:
/**
* @author PengHuAnZhi
* @createTime 2021/2/16 15:30
* @projectName SpringCloudDemo
* @className ConfigClientController.java
* @description TODO
*/
@RestController
@Slf4j
@RefreshScope
public class ConfigClientController {
// 因为config仓库以rest形式暴露,所以所有客户端都可以通过config服务端访问到github上对应的文件信息
@Value("${config.info}")
private String configInfo;
@Value("${server.port}")
private String serverPort;
@GetMapping("/configInfo")
public String getConfigInfo() {
return "ServerPort : " + serverPort + "\t"+"configInfo : "+configInfo;
}
}
②、测试
服务没有问题
③、ConfigServer添加消息总线的支持
这里采用第二种通知方式,直接通知配置中心,更加合理
Ⅰ、POM
在
3344
的POM
文件中新增依赖坐标
<!-- 添加消息总线RabbitMQ支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
Ⅱ、YML
新增
RabbitMQ
和management
节点配置
server:
port: 3344
spring:
application:
name: config-center
cloud:
config:
server:
git:
uri: https://github.com/PengHuAnZhi/CloudDemoConfig #Github上的git仓库地址
##搜索目录.这个目录指的是github上的目录
search-paths:
- CloudDemoConfig
##读取分支
label: main
#rabbitmq相关设置
rabbitmq:
host: 39.105.43.3
port: 5672
username: guest
password: guest
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
#暴露 bus刷新配置的端点
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
④、ConfigClient添加消息总线的支持
3355
,3366
配置相同
Ⅰ、POM
<!-- 添加消息总线RabbitMQ支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
Ⅱ、YML
server:
port: 3355
spring:
application:
name: config-client
cloud:
#Config客户端配置
config:
label: main #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称 上诉3个综合就是 master分支上 config-dev.yml
uri: http://localhost:3344
#rabbitmq相关设置
rabbitmq:
host: 39.105.43.3
port: 5672
username: guest
password: guest
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
#暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
⑤、测试
如果服务运行期间一直循环报java.net.SocketException: socket closed
,那就是你云服务器的安全组没有开,又或者是docker
镜像的端口映射不对,特别注意是要配置两个映射端口
重启服务,访问测试
git
仓库version
改为5
再次查看
3344
,发现正常更新
发送
Post
请求
curl -X POST "http://localhost:3344/actuator/bus-refresh"
再次访问
3355
和3366
查看
RabbitMQ
的Topic
订阅主题,发现确有一个名叫springCloudBus
的Topic
!
4、动态刷新的定点通知
在配置更新后,我们有时候有这种需求,只希望某一部分服务更新配置,另一部分不更新,那么就需要进行定点通知,放在本文中,也就是只通知
3355
或者3366
,另一个不通知
①、一个小公式
http://localhost:配置中心的端口号/actuator/bus-refresh/
{destination}
请求就会发给
config server
并通过destination
参数类指定需要更新配置的服务或实例如:
curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355" #只通知3355,config-client为服务名
curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3366" #只通知3366
②、测试
修改
version
发送通知
再次访问