当前位置: 首页 > news >正文

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、ConfigServergitHub 上面读取配置信息。并在 rabbitmq 上订阅。

        2、ConfigClient 从 ConfigServer上面读取配置信息。并在 rabbitmq 上订阅。

        3、运维人员手动修改远程 gitHub 上的配置信息。

        4、手动给 ConfigServer 发送 post 请求,告诉监听器配置信息发生了变化,需要刷新。

        5、ConfigServer 发送需要刷新的消息给 rabbitmq

        6、ConfigClient 接收到了 rabbitmq 发送的需要刷新的消息。

        7、ConfigClient 重新从 ConfigServer上面读取配置信息。

相关文章:

SpringCloud Bus 消息总线

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

汽车屏类产品(五):仪表Cluster常用芯片i.MX117x

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

SQLiteC/C++接口详细介绍之sqlite3类(三)

快速跳转文章列表&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;二&#xff09; 下一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;四&#xff09; 6.sqlite3_create_module与sqlite3_create_module_v2函数…...

Xcode调试Qt 源码

在Mac下使用Xcode 开发Qt程序&#xff0c;由于程序断点或者崩溃后&#xff0c;Qt库的堆栈并不能够正确定位到源码的cpp文件&#xff0c;而是显示的是汇编代码&#xff0c;导致不直观的显示。 加载的其他三方库都是同理。 所以找了攻略和研究后&#xff0c;写的这篇文章。 一&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中的多值返回&#xff1a;解锁函数返回值的神奇力量 在C编程中&#xff0c;有时候我们需要从函数中返回多个值。虽然C中的函数通常只能返回一个值&#xff0c;但有几种技术和惯用法可以实现返回多个值的效果。本文将介绍C中实现多值返回的几种常用方法&#xff0c;包括引用、指…...

D咖智能咖啡机:营业利器,品质与效率的完美结合

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

江科大stm32学习笔记【6-2】——定时器定时中断定时器外部时钟

一.定时器定时中断 1.原理 2.硬件 3.程序 此时CK_PSC72M&#xff0c;定时1s&#xff0c;也就是定时频率为1Hz&#xff0c;所以可以PSC7200-1,ARR10000-1。 Timer.c: #include "stm32f10x.h" // Device headerextern uint16_t Num;//声明跨文件的…...

go优雅重试

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

Python最常用的库

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

C++面试100问(八)

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

【Git】Github 上commit后,绿格子contribution却不显示?不知道怎么弥补?解决方法在这里

github 上commit后&#xff0c;绿格子&#xff08;contribution&#xff09;却不显示 问题描述 今天一直在github上面commit代码&#xff0c;但是github中并没有显示自己的contribution&#xff08;没有绿色的格子&#xff09;&#xff0c;全是空白&#xff0c;网上一查是因为…...

【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 五层模型&#xff08;或七层模型&#xff09;是什么&#xff0c;每一层的作用是什么 应用层&#xff1a;又可细分为应用层、表示层、会话层。其中应用层主要做的工作就是为应用程序提供服务&#xff0c;常见的协议为 HTTP、HTTPS、DNS等&#xff1b;表示层主要做的工作…...

C++进阶:详解多态(多态、虚函数、抽象类以及虚函数原理详解)

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

【Hadoop大数据技术】——MapReduce经典案例实战(倒排索引、数据去重、TopN)

&#x1f4d6; 前言&#xff1a;MapReduce是一种分布式并行编程模型&#xff0c;是Hadoop核心子项目之一。实验前需确保搭建好Hadoop 3.3.5环境、安装好Eclipse IDE &#x1f50e; 【Hadoop大数据技术】——Hadoop概述与搭建环境&#xff08;学习笔记&#xff09; 目录 &#…...

02、字面量与变量

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

docker的常用指令

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

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...