SpringCloud Bus 消息总线
一、前言
接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第八篇,即介绍 Bus 消息总线。
二、概述
2.1 遗留的问题
在上一篇文章的最后,我们提出了一个不想手动刷新微服务的问题,即想要实现分布式自动刷新配置功能。Spring Cloud Bus 配合 Spring Cloud Config 使用就可以实现配置的动态刷新。
2.2 Bus 是什么
Spring Cloud Bus 是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了 Java 的事件处理机制和消息中间件的功能。Spring Clud Bus 目前支持 RabbitMQ 和 Kafka 两种中间件。
2.3 Bus 作用
Spring Cloud Bus 能管理和传播分布式系统间的消息,就像一个分布式执行器,可用于广播状态更改、事件推送等,也可以当作微服务间的通信通道。
2.4 什么是消息总线
在微服务架构的系统中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称它为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。
2.5 基本原理
所有的 ConfigClient 实例都监听 MQ 中同一个 topic(默认是 springCloudBus)。当一个服务刷新数据的时候,它会把这个信息放入到 Topic 中,这样其它监听同一 Topic 的服务就能得到通知,然后去更新自身的配置。
三、RabbitMQ 环境配置
使用 Spring Cloud Bus 需要安装 rabbitmq,安装教程在这里,安装完毕后启动,登录,效果如下图:
等到后面的案例搭建完成之后,会自动的生成一个交换机,如下图:
四、Bus 动态刷新全局广播
4.1 设计思想
一共有两种设计思想,第一种是利用消息总线触发一个客户端,另外一种是利用消息总线触发一个服务端。
4.1.1 触发一个客户端
利用消息总线触发一个客户端 /bus/refresh,而刷新所有客户端的配置,如下图:
4.1.2 触发一个服务端
利用消息总线触发一个服务端 ConfigServer 的 /bus/refresh 端点,而刷新所有客户端的配置,如下图:
4.1.3 设计选型
触发一个服务端的架构(4.1.2)显然更合适一些,因为如果选择架构一就会打破了微服务的职责单一性,因为微服务本身是业务模块,它本不应该承担配置刷新的职责。并且破坏了微服务各节点的对等性。还存在一定的局限性。例如,微服务在迁移时,它的网络地址常常会发生变化,此时如果想要做到自动刷新,那就会增加更多的修改。
4.2 新建工程
为了演示广播效果,增加复杂度,再以 3355 为模板再制作一个 3366,即新创建一个 cloud-config-center-3366 模块,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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.springcloud</groupId><artifactId>SpringCloud</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>cloud-config-center-3366</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><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>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: 3366spring:application:name: config-clientcloud:#Config客户端配置config:label: master #分支名称name: config #配置文件名称profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.ymluri: http://localhost:3344 #配置中心地址#服务注册到eureka地址
eureka:client:service-url:defaultZone: http://localhost:7001/eureka# 暴露监控端点
management:endpoints:web:exposure:include: "*"
主启动类的代码如下所示:
@EnableEurekaClient
@SpringBootApplication
public class ConfigClientMain3366
{public static void main(String[] args){SpringApplication.run(ConfigClientMain3366.class,args);}
}
业务类 controller 代码如下所示:
package com.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 configInfo(){return "serverPort: "+serverPort+"\t\n\n configInfo: "+configInfo;}
}
4.3 服务端添加消息总线支持
给 cloud-config-center-3344 配置中心模块服务端添加消息总线支持,pom.xml 添加如下的依赖:
<!--添加消息总线RabbitMQ支持-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
修改 application.yml ,添加 rabbitmq 的相关配置,如下:
server:port: 3344spring:application:name: cloud-config-center #注册进Eureka服务器的微服务名cloud:config:server:git:uri: https://github.com/BuGeiQianJiuZa/springcloud-config.git #GitHub上面的git仓库名字####搜索目录search-paths:- springcloud-config####读取分支label: master
#rabbitmq相关配置
rabbitmq:host: localhostport: 5672username: guestpassword: guest#服务注册到eureka地址
eureka:client:service-url:defaultZone: http://localhost:7001/eureka##rabbitmq相关配置,暴露bus刷新配置的端点
management:endpoints: #暴露bus刷新配置的端点web:exposure:include: 'bus-refresh'
4.4 客户端添加消息总线支持
给 cloud-config-client-3355 客户端添加消息总线支持,pom.xml 添加如下的依赖:
<!--添加消息总线RabbitMQ支持-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
修改 bootstrap.yml ,添加 rabbitmq 的相关配置,如下:
server:port: 3355spring:application:name: config-clientcloud:#Config客户端配置config:label: master #分支名称name: config #配置文件名称profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取uri: http://localhost:3344 #配置中心地址k#rabbitmq相关配置 15672是Web管理界面的端口;5672是MQ访问的端口rabbitmq:host: localhostport: 5672username: guestpassword: guest#服务注册到eureka地址
eureka:client:service-url:defaultZone: http://localhost:7001/eureka
# 暴露监控端点
management:endpoints:web:exposure:include: "*" # 'refresh'
给 cloud-config-client-3366 客户端添加消息总线支持,pom.xml 添加如下的依赖:
<!--添加消息总线RabbitMQ支持-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
修改 bootstrap.yml ,添加 rabbitmq 的相关配置,如下:
server:port: 3366spring:application:name: config-clientcloud:#Config客户端配置config:label: master #分支名称name: config #配置文件名称profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取uri: http://localhost:3344 #配置中心地址k#rabbitmq相关配置 15672是Web管理界面的端口;5672是MQ访问的端口rabbitmq:host: localhostport: 5672username: guestpassword: guest#服务注册到eureka地址
eureka:client:service-url:defaultZone: http://localhost:7001/eureka
# 暴露监控端点
management:endpoints:web:exposure:include: "*" # 'refresh'
4.5 测试
分别启动 cloud-eureka-server7001、cloud-config-client-3344、cloud-config-client-3355 和 cloud-config-client-3366,然后在 gitHub 上修改版本信息,如下图:
然后给服务端发送一次 post 请求:curl -X POST "http://localhost:3344/actuator/bus-refresh"
输入 http://config-3344.com:3344/config-dev.yml,测试配置中心,如下图:
输入 http://config-3344.com:3344/config-dev.ymlhttp://localhost:3355/configInfo,测试 3355 客户端,如下图:
输入 http://localhost:3355/configInfo,测试 3366 客户端,如下图:
可以看到,通过这种方式,所有的客户端的配置信息都已经更新了。
五、Bus 动态刷新定点通知
5.1 思想
现在不想全部通知,只想定点通知,只通知 3355,不想通知 3366,又该怎么办呢?
5.2 解决方案
指定具体某一个实例生效而不是全部是有一个公式的,即:
http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}
/bus/refresh 请求不再发送到具体的服务实例上,而是发给 config server 并通过 destination 参数类指定需要更新配置的服务或实例。
5.3 案例
我们这里以刷新运行在 3355 端口上的 config-client 为例,更新 gitHub 上的 version 版本,如下:
然后执行以下的命令:
curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"
输入 http://localhost:3355/configInfo,测试 3355 客户端,如下图:
输入 http://localhost:3366/configInfo,测试 3366 客户端,如下图:
可以看到,通过这种方式,只有 3355 的客户端的配置信息更新了。
5.4 总结
1、ConfigServer 从 gitHub 上面读取配置信息。并在 rabbitmq 上订阅。
2、ConfigClient 从 ConfigServer上面读取配置信息。并在 rabbitmq 上订阅。
3、运维人员手动修改远程 gitHub 上的配置信息。
4、手动给 ConfigServer 发送 post 请求,告诉监听器配置信息发生了变化,需要刷新。
5、ConfigServer 发送需要刷新的消息给 rabbitmq。
6、ConfigClient 接收到了 rabbitmq 发送的需要刷新的消息。
7、ConfigClient 重新从 ConfigServer上面读取配置信息。
相关文章:

SpringCloud Bus 消息总线
一、前言 接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第八篇,即介绍 Bus 消息总线。 二、概述 2.1 遗留的问题 在上一篇文章的最后,我…...

汽车屏类产品(五):仪表Cluster常用芯片i.MX117x
前言: 仪表一般就是指方向盘前面那个表盘。做仪表的芯片最主要需要支持显示Display,而仪表的主要排版布局多种多样,但是主旨显示内容不尽相同。 仪表需求: 1、rpm转速表盘 仪表Cluster一般会有转速表盘rpm,单位一般是x1000,大部分汽车仪表范围就是0~8,也就是最高8000…...

SQLiteC/C++接口详细介绍之sqlite3类(三)
快速跳转文章列表:SQLite—系列文章目录 上一篇:SQLiteC/C接口详细介绍之sqlite3类(二) 下一篇:SQLiteC/C接口详细介绍之sqlite3类(四) 6.sqlite3_create_module与sqlite3_create_module_v2函数…...

Xcode调试Qt 源码
在Mac下使用Xcode 开发Qt程序,由于程序断点或者崩溃后,Qt库的堆栈并不能够正确定位到源码的cpp文件,而是显示的是汇编代码,导致不直观的显示。 加载的其他三方库都是同理。 所以找了攻略和研究后,写的这篇文章。 一&a…...

CVE-2019-5782:kArgumentsLengthType 设置偏小导致优化阶段可以错误的去除 CheckBound 节点
文章目录 环境搭建漏洞分析笔者初分析笔者再分析漏洞触发源码分析 漏洞利用总结 环境搭建 sudo apt install pythongit reset --hard b474b3102bd4a95eafcdb68e0e44656046132bc9 export DEPOT_TOOLS_UPDATE0 gclient sync -D// debug version tools/dev/v8gen.py x64.debug ni…...

uni-app微信小程序上拉加载,下拉刷新
pages.json配置官网链接 onPullDownRefresh、onReachBottom函数跟生命周期同级 data() {return {orderList:[],total: null, //总共多少条数据page: 1,pageSize: 10,} }, onLoad() {}, mounted(){this.getInfo() }, methods:{getInfo(){API.getListxxx().then(res > {const…...
HTML案例-2.标签综合练习
目录 效果 知识点 1.图像标签 2.链接标签 3.锚点定位 4.base标签 源码 页面1 页面2 效果 知识点 1.图像标签 <img src="图像URL" /> 单标签 属性 属性值 描述 src URL 图像的路径 alt 文本...

C++中的多值返回:解锁函数返回值的神奇力量
C中的多值返回:解锁函数返回值的神奇力量 在C编程中,有时候我们需要从函数中返回多个值。虽然C中的函数通常只能返回一个值,但有几种技术和惯用法可以实现返回多个值的效果。本文将介绍C中实现多值返回的几种常用方法,包括引用、指…...

D咖智能咖啡机:营业利器,品质与效率的完美结合
D咖作为中国知名国产商用全自动咖啡机品牌,持续引领商用全自动智能咖啡机赛道技术、产品、创新的行业新标准,目前为全国几十个地区提供全场景自助咖啡机解决方案,并获得了广泛的认可和口碑。 一、便捷操作:一键即可享受美味咖啡 在…...

江科大stm32学习笔记【6-2】——定时器定时中断定时器外部时钟
一.定时器定时中断 1.原理 2.硬件 3.程序 此时CK_PSC72M,定时1s,也就是定时频率为1Hz,所以可以PSC7200-1,ARR10000-1。 Timer.c: #include "stm32f10x.h" // Device headerextern uint16_t Num;//声明跨文件的…...

go优雅重试
实现思路: 重试配置定义最大重试次数和固定重试间隔;使用接口优雅传递可选重试配置参数;重试的模板方法必须返回错误,且只有一个返回值;如果需要使用被重试方法的返回值,使用匿名方法包一层真实方法并在匿…...

Python最常用的库
本文章主要为大家总结,9个Python最常用的包及使用案例 1 NumPy 描述: NumPy 是 Python 的一个扩展库,支持高维数组与矩阵运算,并为数组运算提供了大量的数学函数库。它是科学计算中的基础包之一,用于处理大型多维数组和矩阵的运…...

C++面试100问(八)
C中栈溢出的解决办法有哪些? 1)、增加栈内存的数目;如果是不超过栈大小但是分配值小的,就增大分配的大小 2)、使用堆内存;具体实现由很多种方法可以直接把数组定义改成指针,然后动态申请内存;也可以把局部变…...

【Git】Github 上commit后,绿格子contribution却不显示?不知道怎么弥补?解决方法在这里
github 上commit后,绿格子(contribution)却不显示 问题描述 今天一直在github上面commit代码,但是github中并没有显示自己的contribution(没有绿色的格子),全是空白,网上一查是因为…...

【Vue3】源码解析-Runtime
文章目录 系列文章packages/runtime-dom/src/index.ts初始化创建renderermount \src\runtime-core\component.jsh.tspackages/runtime-core/src/renderer.ts挂载及卸载DOM节点render packages/runtime-dom/src/nodeOps.tspackages/runtime-core/src/apiCreateApp.ts创建appmoun…...

常见面试题之计算机网络
1. OSI 五层模型(或七层模型)是什么,每一层的作用是什么 应用层:又可细分为应用层、表示层、会话层。其中应用层主要做的工作就是为应用程序提供服务,常见的协议为 HTTP、HTTPS、DNS等;表示层主要做的工作…...

C++进阶:详解多态(多态、虚函数、抽象类以及虚函数原理详解)
C进阶:详解多态(多态、虚函数、抽象类以及虚函数原理详解) 结束了继承的介绍:C进阶:详细讲解继承 那紧接着的肯定就是多态啦 文章目录 1.多态的概念2.多态的定义和实现2.1多态的构成条件2.2虚函数2.2.1虚函数的概念2…...

【Hadoop大数据技术】——MapReduce经典案例实战(倒排索引、数据去重、TopN)
📖 前言:MapReduce是一种分布式并行编程模型,是Hadoop核心子项目之一。实验前需确保搭建好Hadoop 3.3.5环境、安装好Eclipse IDE 🔎 【Hadoop大数据技术】——Hadoop概述与搭建环境(学习笔记) 目录 &#…...

02、字面量与变量
二、字面量与变量 文章目录 二、字面量与变量1、字面量字面量类型扩展:特殊字符 2、变量进制转换 3、数据类型 1、字面量 字面量又叫做常量,字面值常量,告诉程序员数据在程序中的书写格式。 字面量类型 整数类型(int):不带小数点…...

docker的常用指令
docker的常用指令 从docker镜像仓库,搜索所有和mysql有关的镜像 docker search mysql 从docker仓库拉取mysql docker pull mysql这里的mysql是指使用search搜索出来的所有容器的NAME 如果和我一样遇到以下问题: 我可以登录阿里云的官网,找…...

19 OpenCV 霍夫曼变换检测圆
文章目录 cv::HoughCircles算子参数示例 cv::HoughCircles 因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波。 基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步: 检测边缘,发现可能…...

leetcode代码记录(摆动序列
目录 1. 题目:2. 我的代码:小结: 1. 题目: 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等…...

django学习笔记
django学习笔记 http://djangobook.py3k.cn/2.0/chapter05/ 文章目录 django学习笔记模型 models.py1、定义数据模型2、模型安装3、创建数据表4、数据表的增删改查4.1 增加4.2 删除4.3 修改4.4 查询4.5 模糊查询4.6 排序&连锁查询4.7 限制返回数据 5、模型使用实战 模型 m…...

Python环境安装及Selenium引入
Python环境安装 环境下载 Download Python | Python.org 环境安装 需使用管理员身份运行 查看环境是否安装成功 python --version 如果未成功则检查环境变量配置 安装 Selenium 库 pip install selenium Selenium 可以模拟用户在浏览器中的操作,如点击按钮、填写…...

【gpt实践】实用咒语分享
直接上咒语了,大家可以自行实践。 1、忽略先前所有的提示 有时候gpt会停留在之前的问题中,导致回答当前问题带着之前问题结论。 2、忽略所有的客套话 我们只是需要有用的信息,有时候gpt客套话会混淆视听。 3、给出非常简短明确的答案 同样…...

Linux用户和权限
一、root用户(超级管理员) 普通用户的权限,一般在其HOME目录内是不受限的 一旦出了HOME目录,大多数地方,普通用户仅有只读和执行权限,无修改权限 二、su 和 exit命令 语法:su [ - ] 【用户…...

git svn混用
背景 项目代码管理初始使用的svn, 由于svn代码操作,无法在本地暂存,有诸多不便,另外本人习惯使用git. 所以决定迁移至git管理 迁移要求: 保留历史提交记录 迁移流程 代码检出 git svn svn_project_url git代码提交 修改本…...

FPGA静态时序分析与约束(三)、读懂vivado时序报告
系列文章目录 FPGA静态时序分析与约束(一)、理解亚稳态 FPGA静态时序分析与约束(二)、时序分析 文章目录 系列文章目录前言一、时序分析回顾二、打开vivado任意工程2.1 工程布局路由成功后,点击vivado左侧**IMPLEMENT…...

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Badge)
可以附加在单个组件上用于信息标记的容器组件。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 支持单个子组件。 说明: 子组件类型:系统组件和自定义组件…...

Python程序设计基础——代码习题
1 __name__属性 import demodef main():if __name__ __main__:print(这个程序被直接运行。)elif __name__demo:print(这个程序作为模块被使用。) main()3.3 编写程序,生成包含1000个0~100之间的随机整数,并统计每个元素出现的次数。 import randomx[r…...