SpringCloud 微服务全栈体系(十)
第十章 RabbitMQ
一、初识 MQ
1. 同步和异步通讯
-
微服务间通讯有同步和异步两种方式:
-
同步通讯:就像打电话,需要实时响应。
-
异步通讯:就像发邮件,不需要马上回复。
-

- 两种方式各有优劣,打电话可以立即得到响应,但是你却不能跟多个人同时通话。发送邮件可以同时与多个人收发邮件,但是往往响应会有延迟。
1.1 同步通讯
- 之前学习的 Feign 调用就属于同步方式,虽然调用可以实时得到结果,但存在下面的问题:

-
总结:
-
同步调用的优点:
- 时效性较强,可以立即得到结果
-
同步调用的问题:
- 耦合度高
- 性能和吞吐能力下降
- 有额外的资源消耗
- 有级联失败问题
-
1.2 异步通讯
-
异步调用则可以避免上述问题:
-
我们以购买商品为例,用户支付后需要调用订单服务完成订单状态修改,调用物流服务,从仓库分配响应的库存并准备发货。
-
在事件模式中,支付服务是事件发布者(publisher),在支付完成后只需要发布一个支付成功的事件(event),事件中带上订单 id。
-
订单服务和物流服务是事件订阅者(Consumer),订阅支付成功的事件,监听到事件后完成自己业务即可。
-
为了解除事件发布者与订阅者之间的耦合,两者并不是直接通信,而是有一个中间人(Broker)。发布者发布事件到 Broker,不关心谁来订阅事件。订阅者从 Broker 订阅事件,不关心谁发来的消息。
-

-
Broker 是一个像数据总线一样的东西,所有的服务要接收数据和发送数据都发到这个总线上,这个总线就像协议一样,让服务间的通讯变得标准和可控。
-
好处:
-
吞吐量提升:无需等待订阅者处理完成,响应更快速
-
故障隔离:服务没有直接调用,不存在级联失败问题
-
调用间没有阻塞,不会造成无效的资源占用
-
耦合度极低,每个服务都可以灵活插拔,可替换
-
流量削峰:不管发布事件的流量波动多大,都由 Broker 接收,订阅者可以按照自己的速度去处理事件
-
-
缺点:
- 架构复杂了,业务没有明显的流程线,不好管理
- 需要依赖于 Broker 的可靠、安全、性能
-
好在现在开源软件或云平台上 Broker 的软件是非常成熟的,比较常见的一种就是 MQ 技术。
2. 技术对比
- MQ,中文是消息队列(MessageQueue),字面来看就是存放消息的队列。也就是事件驱动架构中的 Broker。
2.1 比较常见的 MQ 实现
- ActiveMQ
- RabbitMQ
- RocketMQ
- Kafka
2.2 几种常见 MQ 的对比
| RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
|---|---|---|---|---|
| 公司/社区 | Rabbit | Apache | 阿里 | Apache |
| 开发语言 | Erlang | Java | Java | Scala&Java |
| 协议支持 | AMQP,XMPP,SMTP,STOMP | OpenWire,STOMP,REST,XMPP,AMQP | 自定义协议 | 自定义协议 |
| 可用性 | 高 | 一般 | 高 | 高 |
| 单机吞吐量 | 一般 | 差 | 高 | 非常高 |
| 消息延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒以内 |
| 消息可靠性 | 高 | 一般 | 高 | 一般 |
-
追求可用性:Kafka、 RocketMQ 、RabbitMQ
-
追求可靠性:RabbitMQ、RocketMQ
-
追求吞吐能力:RocketMQ、Kafka
-
追求消息低延迟:RabbitMQ、Kafka
二、快速入门
1. 安装 RabbitMQ
1.1 单机部署
- 在 Centos7 虚拟机中使用 Docker 来安装。
1.1.1 下载镜像
- 方式一:在线拉取
docker pull rabbitmq:3-management
-
方式二:从本地加载 - 资料已经提供了镜像包:
(见专栏 -> 全栈资料包 -> 资源包/02_cloud)- 上传到虚拟机中后,使用命令加载镜像即可:
docker load -i mq.tar
1.1.2 安装 MQ
- 执行下面的命令来运行 MQ 容器:
docker run \-e RABBITMQ_DEFAULT_USER=alex \-e RABBITMQ_DEFAULT_PASS=123321 \--name mq \--hostname mq1 \-p 15672:15672 \-p 5672:5672 \-d \rabbitmq:3-management
1.2 集群部署
集群分类
-
在 RabbitMQ 的官方文档中,讲述了两种集群的配置方式:
- 普通模式:普通模式集群不进行数据同步,每个 MQ 都有自己的队列、数据信息(其它元数据信息如交换机等会同步)。例如我们有 2 个 MQ:mq1,和 mq2,如果你的消息在 mq1,而你连接到了 mq2,那么 mq2 会去 mq1 拉取消息,然后返回给你。如果 mq1 宕机,消息就会丢失。
- 镜像模式:与普通模式不同,队列会在各个 mq 的镜像节点之间同步,因此你连接到任何一个镜像节点,均可获取到消息。而且如果一个节点宕机,并不会导致数据丢失。不过,这种方式增加了数据同步的带宽消耗。
1.3 MQ 的基本结构

-
RabbitMQ 中的一些角色:
- publisher:生产者
- consumer:消费者
- exchange:交换机,负责消息路由
- queue:队列,存储消息
- virtualHost:虚拟主机,隔离不同租户的 exchange、queue、消息的隔离
2. RabbitMQ 消息模型
- RabbitMQ 官方提供了 5 个不同的 Demo 示例,对应了不同的消息模型:

3. 导入 Demo 工程
- 资料提供了一个 Demo 工程,mq-demo:
(见专栏 -> 全栈资料包 -> 资源包/02_cloud)

- 导入后可以看到结构如下:

-
包括三部分:
- mq-demo:父工程,管理项目依赖
- publisher:消息的发送者
- consumer:消息的消费者
4. 入门案例
- 简单队列模式的模型图:

-
官方的 HelloWorld 是基于最基础的消息队列模型来实现的,只包括三个角色:
- publisher:消息发布者,将消息发送到队列 queue
- queue:消息队列,负责接受并缓存消息
- consumer:订阅队列,处理队列中的消息
4.1 publisher 实现
-
思路:
- 建立连接
- 创建 Channel
- 声明队列
- 发送消息
- 关闭连接和 channel
-
代码实现:
package com.alex.mq.helloworld;import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.junit.Test;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class PublisherTest {@Testpublic void testSendMessage() throws IOException, TimeoutException {// 1.建立连接ConnectionFactory factory = new ConnectionFactory();// 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码factory.setHost("192.168.150.101");factory.setPort(5672);factory.setVirtualHost("/");factory.setUsername("alex");factory.setPassword("123321");// 1.2.建立连接Connection connection = factory.newConnection();// 2.创建通道ChannelChannel channel = connection.createChannel();// 3.创建队列String queueName = "simple.queue";channel.queueDeclare(queueName, false, false, false, null);// 4.发送消息String message = "hello, rabbitmq!";channel.basicPublish("", queueName, null, message.getBytes());System.out.println("发送消息成功:【" + message + "】");// 5.关闭通道和连接channel.close();connection.close();}
}
4.2 consumer 实现
-
代码思路:
- 建立连接
- 创建 Channel
- 声明队列
- 订阅消息
-
代码实现:
package com.alex.mq.helloworld;import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class ConsumerTest {public static void main(String[] args) throws IOException, TimeoutException {// 1.建立连接ConnectionFactory factory = new ConnectionFactory();// 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码factory.setHost("192.168.150.101");factory.setPort(5672);factory.setVirtualHost("/");factory.setUsername("alex");factory.setPassword("123321");// 1.2.建立连接Connection connection = factory.newConnection();// 2.创建通道ChannelChannel channel = connection.createChannel();// 3.创建队列String queueName = "simple.queue";channel.queueDeclare(queueName, false, false, false, null);// 4.订阅消息channel.basicConsume(queueName, true, new DefaultConsumer(channel){@Overridepublic void handleDelivery(String consumerTag, Envelope envelope,AMQP.BasicProperties properties, byte[] body) throws IOException {// 5.处理消息String message = new String(body);System.out.println("接收到消息:【" + message + "】");}});System.out.println("等待接收消息。。。。");}
}
5. 总结
- 基本消息队列的消息发送流程:
-
建立 connection
-
创建 channel
-
利用 channel 声明队列
-
利用 channel 向队列发送消息
- 基本消息队列的消息接收流程:
-
建立 connection
-
创建 channel
-
利用 channel 声明队列
-
定义 consumer 的消费行为 handleDelivery()
-
利用 channel 将消费者与队列绑定
相关文章:
SpringCloud 微服务全栈体系(十)
第十章 RabbitMQ 一、初识 MQ 1. 同步和异步通讯 微服务间通讯有同步和异步两种方式: 同步通讯:就像打电话,需要实时响应。 异步通讯:就像发邮件,不需要马上回复。 两种方式各有优劣,打电话可以立即得…...
[原创]Cadence17.4,win64系统,构建CIS库
目录 1、背景介绍 2、具体操作流程 3、遇到问题、分析鉴别问题、解决问题 4、借鉴链接并评论 1、背景介绍 CIS库,绘制原理图很方便,但是需要在Cadence软件与数据库之间建立联系,但是一直不成功,花费半天时间才搞明白如何建立关系并…...
Python 海龟绘图基础教学教案(一)
Python 海龟绘图——第 1 题 题目:绘制下面的图形 解析: 考察 turtle 基本命令,绘制直线,使用 forward,可缩写为 fd。 答案: import turtle as t t.fd(100) # 或者使用 t.forward(100) t.done() Python 海…...
JUC并发编程系列(一):Java线程
前言 JUC并发编程是Java程序猿必备的知识技能,只有深入理解并发过程中的一些原则、概念以及相应源码原理才能更好的理解软件开发的流程。在这篇文章中荔枝会梳理并发编程的基础,整理有关Java线程以及线程死锁的知识,希望能够帮助到有需要的小…...
双向链表相关代码
DLinkList.h // // DLinkList.hpp // FirstP // // Created by 赫赫 on 2023/10/31. // 双向链表相关代码:双向链表、循环双向链表#ifndef DLinkList_hpp #define DLinkList_hpp #include <stdio.h> #include <stdlib.h> #include <iostream>…...
[每周一更]-(第70期):常用的GIT操作命令
1、增删文件 # 添加当前目录的所有文件到暂存区 $ git add .# 添加指定文件到暂存区 $ git add <file1> <file2> ...# 添加指定目录到暂存区,包括其子目录 $ git add <dir># 删除工作区文件,并且将这次删除放入暂存区 $ git rm [file…...
Leetcode-283 移动零
count记录0的个数,不为0的数取代0位置,最后把剩余位置置零 class Solution {public void moveZeroes(int[] nums) {int count 0;for(int i0;i<nums.length;i){if(nums[i]0){count;}else{nums[i-count]nums[i];}}for(int inums.length-count;i<nu…...
爱上C语言:函数递归,青蛙跳台阶图文详解
🚀 作者:阿辉不一般 🚀 你说呢:生活本来沉闷,但跑起来就有风 🚀 专栏:爱上C语言 🚀作图工具:draw.io(免费开源的作图网站) 如果觉得文章对你有帮助的话,还请…...
Pycharm 对容器中的 Python 程序断点远程调试
pycharm如何连接远程服务器的docker容器有两种方法: 第一种:pycharm通过ssh连接已在运行中的docker容器 第二种:pycharm连接docker镜像,pycharm运行代码再自动创建容器 本文是第一种方法的教程,第二种请点击以上的链接…...
自动驾驶行业观察之2023上海车展-----车企发展趋势(3)
合资\外资发展 宝马:i7、iX1新车亮相,未来将持续发力电动化、数字化(座舱) 宝马在本次车展重点展示了电动化产品,新发车型为i7 M70L、iX1、及i vision Dee概念车等车型。 • 展示重点:电动化数字化&#…...
day55【动态规划子序列】392.判断子序列 115.不同的子序列
文章目录 392.判断子序列115.不同的子序列 392.判断子序列 题目链接:力扣链接 讲解链接:代码随想录讲解链接 题意:给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不…...
c语言中磁盘文件的分类
#include <stdio.h> /*磁盘文件的分类: * 一个文件通常是磁盘上一段命名的存储区计算机的存储在物理上是二进制的, * 所以物理上所有的磁盘文件本质上都是一样的:以字节为单位进行顺序存储 * 从用户或者操作系统使用的角度(…...
Unity适配微信
使用的是微信开发的插件 GitHub - wechat-miniprogram/minigame-unity-webgl-transform 路径相关: Unity:Application.streamingAssetsPath --> 配置的cdn路径StreamingAssets...
虚拟机本地磁盘在线扩容
背景 虚拟机本地盘对于host物理机来说就是一个LVM卷,虚拟化(libvirt+kvm_qemu)已经支持虚拟机磁盘在线调整,配合物理机lvm管理工具可实现云场景下虚拟机磁盘在线扩容功能。环境检查 (1)虚拟机本地盘信息 <disk type=block device=disk><driver...
ACTIVE_MQ学习
ActiveMq学习①___入门概述https://blog.csdn.net/qq_45905724/article/details/131796502 ActiveMq学习②__安装与控制台https://blog.csdn.net/qq_45905724/article/details/133893214 ActiveMq学习③___Java编码实现ActiveMQ通讯https://blog.csdn.net/qq_45905724/articl…...
【C++初阶】类和对象(上)
【C初阶】类和对象(上) 1.面向对象与面向过程的初步认识2.类的引入3. 类的定义4.类的访问限定符及封装4.1访问限定符4.2封装 5.类的作用域6.类的实例化6.类的对象的大小计算7.类的this指针7.1this指针的引入7.2this指针的一些特性 📃博客主页…...
新版onenet平台安全鉴权的确定与使用
根据onenet官方更新的文档:平台提供开放的API接口,用户可以通过HTTP/HTTPS调用,进行设备管理,数据查询,设备命令交互等操作,在API的基础上,根据自己的个性化需求搭建上层应用。 为提高API访问安…...
容器核心技术-Namespace
一、容器 基于Linux 内核的 Cgroup, Namespace,以及Union FS等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术,由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。 1.1 容器主要特性…...
linux写文件如何保证落盘?
3.1.1. sync sync函数只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束。通常称为 update的系统守护进程会周期性地(一般每隔30秒)调用sync函数。这就保证了定期冲洗内核的块缓冲区。命令 sync也…...
2023 electron最新最简版打包、自动升级详解
这里我将讲解一下从0搭建一个electron最简版架子,以及如何实现打包自动化更新 之前我有写过两篇文章关于electron框架概述以及 常用api的使用,感兴趣的同学可以看看 Electron桌面应用开发 Electron桌面应用开发2 搭建electron 官方文档:ht…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...
41道Django高频题整理(附答案背诵版)
解释一下 Django 和 Tornado 的关系? Django和Tornado都是Python的web框架,但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架,鼓励快速开发和干净、实用的设计。它遵循MVC设计,并强调代码复用。Django有…...
