异步消息组件MQ基础

简介: 本课程介绍MQ的应用场景及RabbitMQ入门,涵盖同步与异步调用区别、消息队列的解耦与流量削峰作用,学习RabbitMQ收发消息、交换机类型、队列特性及在商城项目中的应用。

学习目标

  1. 能够说出MQ的应用场景
  2. 能够编写RabbitMQ收发消息的入门程序
  3. 能够说出工作队列模型的特点
  4. 能够说出发布订阅模型的交换机类型
  5. 能够说出fanout交换机的特性
  6. 能够说出Direct交换机的特性
  7. 能够说出Topic交换机的特性
  8. 能够说出惰性队列的特性
  9. 能够说出优先级队列的特性
  10. 能够说出如何解决MQ消息堆积问题
  11. 能够在商城项目应用MQ

1.初识MQ

1.1 同步调用与异步调用

前边我们学习了微服务之间远程调用方式,通常服务端提供HTTP RESTful接口,客户端通过HTTP Client工具进行远程调用,远程调用工具有RestTemplateOpenFeign、OkHttp等技术,这些技术实现的都是一种类型即同步调用,微服务之间通信还有一种异步调用,什么是同步调用?什么是异步调用?

拿订单支付功能举例,下图表示了同步调用

支付的交互流程如下:

  1. 支付服务调用用户服务扣减余额。
  2. 余额扣减成功后支付服务更新数据库中的交易流水状态为已支付。
  3. 更新成功后支付服务调用交易服务更新订单状态为已支付。

像这种每一步调用者必须等待被调用方完全执行完毕并返回结果之后才能继续执行后续代码,叫同步调用

同步调用就是顺序执行,执行完一步再执行下一步。

什么是异步调用?

异步调用是调用者发出调用后无需等待被调用方完成就可以继续执行其他任务。

举例:

支付的交互流程如下:

  1. 支付服务调用用户服务扣减余额。
  2. 余额扣减成功后支付服务更新数据库中的交易流水状态为已支付。
  3. 更新交易流水成功支付服务向消息中间件发消息(XX订单支付成功),此时支付服务程序执行结束
  4. 消息中间件去通知交易服务更新订单状态
  5. 消息中间件去通知短信服务通知用户订单支付成功啦

上边交互流程中前3步为同步调用,后2步为异步调用

支付服务向消息中间件发过消息后不用等继续执行其它操作,这就是异步调用

现在生活中异步调用的例子很多:

餐厅点餐:

想象一下你去一家餐厅吃饭,你坐下后,服务员过来让你点菜。在这个过程中:

  • 异步调用:你告诉服务员你想要什么菜品,然后服务员把订单送到厨房。你不需要等待食物准备完成,可以继续聊天或浏览菜单。当食物准备好时,服务员会将食物端到你的桌上。
  • 同步调用:如果你必须站在厨房门口等着厨师为你准备食物,那么这就是一个同步的过程。你无法做其他事情,直到食物准备完毕。

医院挂号:

  • 异步调用:打电话挂号,接通电话你告诉工作人员挂哪个科室,工作人员让你挂断电话稍后通过手机查看挂号结果。
  • 同步调用:打电话挂号,接通电话你告诉工作人员挂哪个科室,工作人员开始查看该科室是否有号,并进行挂号,挂号结束告诉你几点来看病,最后挂断电话。

同步调用:

特点:

  • 在同步调用中,调用者必须等待被调用方完全执行完毕并返回结果之后才能继续执行后续代码。
  • 控制流是线性的,即程序按照顺序执行每个操作。
  • 如果被调用方执行时间较长,那么整个程序会处于等待状态,直到该调用完成。

适合场景:

  • 实时性要求较高的场景,例如用户界面操作。
  • 调用简单且执行快速的操作。

优点

  • 简单直观:代码易于理解和编写,因为它是按顺序执行的。
  • 易于调试:由于执行顺序明确,调试起来相对容易。

缺点

  • 阻塞执行:如果一个操作需要很长时间来完成,那么整个程序会被阻塞,不能执行其他任务。
  • 资源浪费:在等待长时间操作完成时,CPU和其他资源可能会处于空闲状态。

异步调用:

特点:

  • 在异步调用中,调用者发出调用后无需等待被调用方完成就可以继续执行其他任务。
  • 被调用方完成操作后,通常会通过回调函数、事件通知或者完成信号等方式告知调用者。
  • 可以提高程序的并发能力和响应速度

适合场景:

  • 需要处理耗时操作,例如网络请求、文件I/O等。
  • 多个操作之间不存在严格的依赖关系。
  • 对系统性能和响应时间有较高要求的应用场景。

优点

  • 提高效率:异步调用可以使程序在等待某些耗时操作完成的同时执行其他任务,提高整体执行效率。
  • 资源利用率高:在等待耗时操作时,可以释放资源给其他任务使用,避免了资源浪费。
  • 更好的用户体验:在网络应用中,用户不必等待页面加载完成就能进行其他操作,提高了用户体验。

缺点

  • 复杂性增加:异步编程通常比同步编程更复杂,因为它涉及更多的控制结构和错误处理逻辑。
  • 调试困难:由于执行路径不是线性的,调试起来相对困难。

1.2 初识MQ

异步调用方式其实就是基于消息通知的方式,一般包含三个角色:

  • 消息发送者:投递消息的人,就是原来的调用方
  • 消息Broker(消息代理/消息中间件):管理、存、转发消息,你可以把它理解成微信服务器
  • 消息接收者:接收和处理消息的人,就是原来的服务提供方

在异步调用中,发送者不再直接同步调用接收者的业务接口,而是发送一条消息投递给消息Broker。然后接收者根据自己的需求从消息Broker那里订阅消息。每当发送方发送消息后,接收者都能获取消息并处理。

这样,发送消息的人和接收消息的人就完全解耦了。

消息Broker,目前常见的实现方案就是消息队列(MessageQueue),简称为MQ.

AI:消息队列的应用场景

  1. 异步处理:
  1. 场景: 当应用程序需要执行耗时的操作(如发送电子邮件、文件上传或下载等)时,可以将这些任务发送到消息队列中,由专门的任务处理程序异步执行。
  2. 好处: 减少了用户的等待时间,提高了用户体验。
  1. 解耦:
  1. 场景: 当一个系统由多个组件组成时,这些组件之间可以使用消息队列进行通信。
  2. 好处: 单个组件的变化不会直接影响到其他组件,提高了系统的可扩展性。
  1. 流量削峰
  1. 场景:在许多互联网应用和服务中,尤其是那些具有明显周期性流量特征的应用(如电商平台、社交网络等),常常会遇到流量突增的情况。例如,在电商促销期间,大量的用户会在短时间内访问网站并提交订单,这种短时间内产生的巨大流量可能会导致服务器过载,影响用户体验甚至导致服务不可用。
  2. 好处:当流量激增时接收到请求会被暂时存储在消息队列中,而不是直接发送到后端服务进行处理。这样做可以避免后端服务因为短时间内处理大量请求而过载。后端服务可以从消息队列中按需拉取消息进行处理。这种异步处理机制可以有效地分散流量峰值,确保后端服务的稳定运行。如下图:

目比较常见的MQ实现:

几种常见MQ的对比:

  • 追求可靠性:RabbitMQ、RocketMQ
  • 追求吞吐(高并发)能力:RocketMQ、Kafka
  • 追求消息低延迟:RabbitMQ、Kafka

这四种的MQ在市场都是非常流行,本课程讲解RabbitMQ。

Spring Boot默认支持AMQP协议,RabbitMQ支持AMQP协议 。

1.3 面试题

MQ有什么应用场景?

2 RabbitMQ入门

2.1 RabbitMQ介绍

RabbitMQ是基于Erlang语言开发的开源消息通信中间件,官网地址:https://www.rabbitmq.com/

RabbitMQ的架构如图:

其中包含几个概念:

  • publisher:生产者,也就是发送消息的应用程序
  • consumer:消费者,也就是消费消息的应用程序
  • queue:队列,存储消息的缓冲区。生产者投递的消息会暂存在消息队列中,等待消费者处理
  • exchange:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。
  • virtual host:虚拟主机,起到数据隔离的作用。每个虚拟主机相互独立,有各自的exchange、queue

上述这些东西都可以在RabbitMQ的管理控制台来管理,下一节我们就一起来学习控制台的使用。

2.2. 安装

已帮大家装好mq,但是这里面有很多冗余的数据,你可以直接启动

  • docker ps -a:查看所有,可以看到有单机mq,和集群的mq1~3
  • docker start mq启动即可

或先删除【建议】

  • docker rm -f mq
  • 然后执行下面的启动脚本即可

或启动时候,命名一个新的

docker run \

-e RABBITMQ_DEFAULT_USER=itheima \

-e RABBITMQ_DEFAULT_PASS=123321 \

-v mq-plugins:/plugins \

--name mq197 \

-p 15672:15672 \

-p 5672:5672 \

-d \

rabbitmq:3.8-management

我们同样基于Docker来安装RabbitMQ,使用下面的命令即可:

找到课前资料下的mq.tar(rabbitmq的镜像文件),上传到/root下。

利用docker load命令加载:docker load -i mq.tar

执行下边的脚本创建容器:

docker run \
 -e RABBITMQ_DEFAULT_USER=itheima \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 -v mq-plugins:/plugins \
 --name mq \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3.8-management

可以看到在安装命令中有两个映射的端口:

  • 15672:RabbitMQ提供的管理控制台的端口
  • 5672:RabbitMQ的消息发送处理接口

安装完成后,我们访问 http://192.168.101.68:15672 即可看到管理控制台。首次访问需要登录,默认的用户名:itheima,密码:123321。登录后即可看到管理控制台总览页面:

2.3. 收发消息

2.3.1 搭建环境

RabbitMQ安装成功后下边我们编写消息发送与消息接收程序实现收发消息,如下图:publisher即消息发送者将消息发送到MQ的队列中,consumer即消息消费者从MQ中接收消息。

RabbitMQ通信采用了AMQP (Advanced Message Queuing Protocol) 协议,因此它具备跨语言的特性,任何语言只要遵循AMQP协议都可以使用RabbitMQ收发消息。

RabbitMQ官方也提供了各种不同语言的客户端API,RabbitMQ官方提供的Java客户端编码相对复杂,一般生产环境下我们更多会结合Spring来使用。而Spring的官方刚好基于RabbitMQ提供了这样一套消息收发的模板工具:SpringAMQP。并且还基于SpringBoot对其实现了自动装配,使用起来非常方便。

SpringAmqp的官方地址:https://spring.io/projects/spring-amqp

SpringAMQP提供了三个功能:

  • 自动声明队列、交换机及其绑定关系
  • 基于注解的监听器模式,异步接收消息
  • 封装了RabbitTemplate工具,用于发送消息

下边使用SpringAMQP实现消息收发,上图是RabbitMQ最简单的工作模型,我们仅作测试使用,这种模式一般很少在生产中使用。

在课前资料给大家提供了一个Demo工程,方便我们学习SpringAMQP的使用:

将其复制到你的工作空间,然后用Idea打开,项目结构如图:

包括三部分:

  • mq-demo:父工程,管理项目依赖
  • publisher:消息的发送者
  • consumer:消息的消费者

在mq-demo这个父工程中,已经配置好了SpringAMQP相关的依赖:

<?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>
  <groupId>cn.itcast.demo</groupId>
  <artifactId>mq-demo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>publisher</module>
    <module>consumer</module>
  </modules>
  <packaging>pom</packaging>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.12</version>
    <relativePath/>
  </parent>
  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
    <!--AMQP依赖,包含RabbitMQ-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    <!--单元测试-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
  </dependencies>
</project>

设置java版本

因此,子工程中就可以直接使用SpringAMQP了。


相关文章
|
29天前
|
监控 Java 测试技术
OOM排查之路:一次曲折的线上故障复盘
本文记录了一次Paimon数据湖与RocksDB集成服务线上频繁OOM的排查历程。通过分析线程暴增、堆外内存泄漏,最终定位到SDK中RocksDB的JNI内存未释放问题,并借助Flink重构写入链路彻底解决。分享了MAT、NMT、async-profiler等工具的实战经验与排查思路,为类似技术栈提供借鉴。
OOM排查之路:一次曲折的线上故障复盘
|
29天前
|
人工智能 JSON 数据挖掘
大模型应用开发中MCP与Function Call的关系与区别
MCP与Function Call是大模型应用中两大关键技术。前者为跨模型标准化通信协议,实现工具与模型解耦;后者是模型调用外部功能的内置机制。二者互补协作,推动AI应用向更开放、灵活、可扩展的方向发展。
|
30天前
|
Java 网络安全 开发工具
[MES]不合格订单接入提醒功能(☆☆☆) 1.代码运行
本文介绍入职后如何快速搭建开发环境并运行项目,包括克隆代码、配置JDK/Maven/Git等工具的求助策略,并模拟真实需求:实现不合格工单超30分钟自动通知(短信/钉钉),涉及Git、Maven、SpringBoot及定时任务技术,提升新人实战能力。
|
29天前
|
canal 关系型数据库 MySQL
微服务原理篇(Canal-Redis)
本课程讲解多数据源同步方案,重点介绍Canal+MQ实现MySQL到Elasticsearch的数据同步机制,涵盖Canal伪装MySQL slave原理、binlog解析、消息顺序性保障,并深入Redis持久化、集群模式、缓存一致性及分布式锁等核心知识点。
 微服务原理篇(Canal-Redis)
|
29天前
|
缓存 关系型数据库 MySQL
微服务原理篇(XXLJOB-幂等-MySQL)
本课程介绍XXL-JOB分布式任务调度平台,涵盖其优势、组成结构及搭建方法,学习如何实现定时任务、避免重复执行,并掌握热点缓存更新、幂等处理、数据库索引优化与SQL调优等实战技能。
|
29天前
|
负载均衡 Java 应用服务中间件
微服务网关与配置中心
本课程围绕Spring Cloud Gateway网关展开,涵盖路由配置、负载均衡、过滤器使用、全局身份校验及Nacos配置管理等内容。通过实战实现微服务统一入口、权限鉴权、前后端联调与配置热更新,提升系统安全与可维护性。
|
30天前
|
关系型数据库 MySQL Java
开发环境搭建
工欲善其事,必先利其器。学习前请确保电脑内存16G以上(建议32G),安装VMware及CentOS7虚拟机,配置网络与IP,远程连接使用FinalShell。苹果用户需安装Docker并部署MySQL8。下载课程资料、Maven仓库及虚拟机镜像,导入后设置IDEA开发环境,配置JDK11、自动导包与编码。通过Git Fork项目至个人仓库并克隆到本地,完成环境搭建。
|
29天前
|
安全 算法 Java
第一章 Java基础
本文系统讲解Java核心知识,涵盖基础语法、面向对象、集合类、异常处理、IO流、多线程、JVM原理、反射泛型及Tomcat优化等内容,结合代码示例与底层机制分析,助力深入理解Java编程与性能调优。
 第一章 Java基础
|
30天前
|
自然语言处理 搜索推荐 Java
ES分布式搜索引擎入门
本课程介绍Elasticsearch的核心概念与应用,涵盖倒排索引原理、IK分词器使用及Java Client操作,实现高效全文检索、增删改查、批量导入、查询优化等功能,提升搜索性能与体验。
ES分布式搜索引擎入门
|
29天前
|
消息中间件 Kafka 数据库
异步消息组件MQ基础
本课程介绍MQ的应用场景及RabbitMQ入门,涵盖同步与异步调用区别、消息队列模型、交换机类型(Fanout、Direct、Topic)、惰性与优先级队列特性,以及消息堆积解决方案,并结合商城项目实践,帮助掌握高效解耦、流量削峰等核心技能。
异步消息组件MQ基础