前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >秒懂消息队列MQ,看这篇就够了!

秒懂消息队列MQ,看这篇就够了!

作者头像
架构师精进
发布于 2023-10-06 06:52:48
发布于 2023-10-06 06:52:48
14.5K023
代码可运行
举报
文章被收录于专栏:公众号文章公众号文章
运行总次数:23
代码可运行

前面介绍了分布式锁以及如何使用Redis实现分布式锁,接下来介绍分布式系统中另外一个非常重要的组件:消息队列

消息队列是大型分布式系统不可缺少的中间件,也是高并发系统的基石中间件,所以掌握好消息队列MQ就变得极其重要。接下来我就将从零开始介绍什么是消息队列?消息队列的应用场景?如何进行选型?如何在Spring Boot项目中整合集成消息队列。

一、消息队列概述

消息队列(Message Queue,简称MQ)指保存消息的一个容器,其实本质就是一个保存数据的队列。

消息中间件是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的构建。

消息中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性的系统架构。目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等。

二、消息队列应用场景

消息中间件在互联网公司使用得越来越多,主要用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。以下介绍消息队列在实际应用中常用的使用场景。异步处理,应用解耦,流量削峰和消息通讯四个场景。

2.1 异步处理

异步处理,就是将一些非核心的业务流程以异步并行的方式执行,从而减少请求响应时间,提高系统吞吐量。

以下单为例,用户下单后需要生成订单、赠送活动积分、赠送红包、发送下单成功通知等一系列业务处理。假设三个业务节点每个使用100毫秒钟,不考虑网络等其他开销,则串行方式的时间是400毫秒,并行的时间只需要200毫秒。这样就大大提高了系统的吞吐量。

2.2 应用解耦

应用解耦,顾名思义就是解除应用系统之间的耦合依赖。通过消息队列,使得每个应用系统不必受其他系统影响,可以更独立自主。

以电商系统为例,用户下单后,订单系统需要通知积分系统。一般的做法是:订单系统直接调用积分系统的接口。这就使得应用系统间的耦合特别紧密。如果积分系统无法访问,则积分处理失败,从而导致订单失败。

加入消息队列之后,用户下单后,订单系统完成下单业务后,将消息写入消息队列,返回用户订单下单成功。积分系统通过订阅下单消息的方式获取下单通知消息,从而进行积分操作。实现订单系统与库存系统的应用解耦。如果,在下单时积分系统系统异常,也不会影响用户正常下单。

2.3 流量削峰

流量削峰也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛。

以秒杀活动为例,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列,后台系统根据消息队列中的消息信息,进行秒杀业务处理。

如上图所示,服务器接收到用户的请求后,首先写入消息队列,后台系统根据消息队列中的请求信息,做后续业务处理。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。

2.4 消息通讯

消息通讯是指应用间的数据通信。消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等点对点通讯。

以上实际是消息队列的两种消息模式,点对点或发布订阅模式。

三、如何选择合适的消息队列

目前使用较多的消息队列有ActiveMQ,RabbitMQ,Kafka,RocketMQ等。面对这么多的中消息队列中间件,如何选择适合我们自身业务的消息中间件呢?

3.1 衡量标准

虽然这些消息队列在功能和特性方面各有优劣,但我们在选型时要有基本衡量标准:

1、首先,是开源。开源意味着,如果有一天你使用的消息队列遇到了一个影响你系统业务的Bug,至少还有机会通过修改源代码来迅速修复或规避这个Bug,解决你的系统的问题,而不是等待开发者发布的下一个版本来解决。

2、其次,是社区活跃度。这个产品必须是近年来比较流行并且有一定社区活跃度的产品。我们知道,开源产品越流行 Bug 越少,因为大部分遇到的 Bug,其他人早就遇到并且修复了。而且在使用过程中遇到的问题,也比较容易在网上搜索到类似的问题并快速找到解决方案。同时,流行开源产品一般与周边生态系统会有一个比较好的集成和兼容。

3、最后,作为一款及格的消息队列,必须具备的几个特性包括:

  • 消息的可靠传递:确保不丢消息;
  • 支持集群:确保不会因为某个节点宕机导致服务不可用,当然也不能丢消息;
  • 性能:具备足够好的性能,能满足绝大多数场景的性能要求。
3.2 选型对比

接下来我们一起看一下有哪些符合上面这些条件,可供选择的开源消息队列产品。以下是关于各个消息队列中间件的选型对比:

特性

Kafka

RocketMQ

RabbitMQ

ActiveMQ

单机吞吐量

10万级

10万级

万级

10万级

开发语言

Scala

Java

Erlang

Java

高可用

分布式

分布式

主从

分布式

消息延迟

ms级

ms级

us级

ms级

消息丢失

理论上不会丢失

理论上不会丢失

消费模式

拉取

推拉

推拉

持久化

文件

内存,文件

内存,文件,数据库

支持协议

自定义协议

自定义协议

AMQP,XMPP, SMTP,STOMP

AMQP,MQTT,OpenWire,STOMP

社区活跃度

管理界面

web console

一般

部署难度

部署方式

独立

独立

独立

独立,嵌入

成熟度

成熟

比较成熟

成熟

成熟

综合评价

优点:拥有强大的性能及吞吐量,兼容性很好。 缺点:由于支持消息堆积,导致延迟比较高。

优点:性能好,稳定可靠,有活跃的中文社区,特点响应快。 缺点:兼容性较差,但随着影响力的扩大,该问题会有改善。

优点:产品成熟,容易部署和使用,拥有灵活的路由配置。 缺点:性能和吞吐量较差,不易进行二次开发。

优点:产品成熟,支持协议多,支持多种语言的客户端。 缺点:社区不活跃,存在消息丢失的可能。

以上四种消息队列都有各自的优劣势,需要根据现有系统的情况,选择最适合的消息队列。

总结起来,电商、金融等对事务性要求很高的,可以考虑RocketMQ;技术挑战不是特别高,用 RabbitMQ 是不错的选择;如果是大数据领域的实时计算、日志采集等场景可以考虑 Kafka。

四、Spring Boot整合RabbitMQ实现消息队列

Spring Boot提供了spring-bootstarter-amqp组件对消息队列进行支持,使用非常简单,仅需要非常少的配置即可实现完整的消息队列服务。

接下来介绍Spring Boot对RabbitMQ的支持。如何在SpringBoot项目中使用RabbitMQ?

4.1 Spring Boot集成RabbitMQ

Spring Boot提供了spring-boot-starter-amqp组件,只需要简单的配置即可与Spring Boot无缝集成。下面通过示例演示集成RabbitMQ实现消息的接收和发送。

第一步,配置pom包。

创建Spring Boot项目并在pom.xml文件中添加spring-bootstarter-amqp等相关组件依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
代码语言:javascript
代码运行次数:0
运行
复制

在上面的示例中,引入Spring Boot自带的amqp组件spring-bootstarter-amqp。

第二步,修改配置文件。

修改application.properties配置文件,配置rabbitmq的host地址、端口以及账户信息。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring.rabbitmq.host=10.2.1.231
spring.rabbitmq.port=5672
spring.rabbitmq.username=zhangweizhong
spring.rabbitmq.password=weizhong1988
spring.rabbitmq.virtualHost=order
代码语言:javascript
代码运行次数:0
运行
复制

在上面的示例中,主要配置RabbitMQ服务的地址。RabbitMQ配置由spring.rabbitmq.* 配置属性控制。virtual-host配置项指定RabbitMQ服务创建的虚拟主机,不过这个配置项不是必需的。

第三步,创建消费者

消费者可以消费生产者发送的消息。接下来创建消费者类Consumer,并使用@RabbitListener注解来指定消息的处理方法。示例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class Consumer {
  @RabbitHandler
  @RabbitListener(queuesToDeclare = @Queue("rabbitmq_queue"))
  public void process(String message) {
    System.out.println("消费者消费消息111=====" + message);
  }
}
代码语言:javascript
代码运行次数:0
运行
复制

在上面的示例中,Consumer消费者通过@RabbitListener注解创建侦听器端点,绑定rabbitmq_queue队列。

(1)@RabbitListener注解提供了@QueueBinding、@Queue、@Exchange等对象,通过这个组合注解配置交换机、绑定路由并且配置监听功能等。

(2)@RabbitHandler注解为具体接收的方法。

第四步,创建生产者

生产者用来产生消息并进行发送,需要用到RabbitTemplate类。与之前的RedisTemplate类似,RabbitTemplate是实现发送消息的关键类。示例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class Producer {
  @Autowired
  private RabbitTemplate rabbitTemplate;
  
  public void produce() {
    String message = new Date() + "Beijing";
    System.out.println("生产者产生消息=====" + message);
    rabbitTemplate.convertAndSend("rabbitmq_queue", message);
  }
}
代码语言:javascript
代码运行次数:0
运行
复制

如上面的示例所示,RabbitTemplate提供了 convertAndSend方法发送消息。convertAndSend方法有routingKey和message两个参数:

(1)routingKey为要发送的路由地址。

(2)message为具体的消息内容。发送者和接收者的queuename必须一致,不然无法接收。

第五步,测试验证。

创建对应的测试类ApplicationTests,验证消息发送和接收是否成功。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
  @Autowired
  Producer producer;
  @Test
  public void contextLoads() throws InterruptedException {
    producer.produce(); 
    Thread.sleep(1*1000);
  }
}
代码语言:javascript
代码运行次数:0
运行
复制

在上面的示例中,首先注入生产者对象,然后调用produce()方法来发送消息。

最后,单击Run Test或在方法上右击,选择Run 'contextLoads()',运行单元测试程序,查看后台输出情况,结果如下图所示。

通过上面的程序输出日志可以看到,消费者已经收到了生产者发送的消息并进行了处理。这是常用的简单使用示例。

4.2 发送和接收实体对象

Spring Boot支持对象的发送和接收,且不需要额外的配置。下面通过一个例子来演示RabbitMQ发送和接收实体对象。

4.2.1 定义消息实体

首先,定义发送与接收的对象实体User类,代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class User implements Serializable {
  public String name;
  public String password;
  // 省略get和set方法
}
代码语言:javascript
代码运行次数:0
运行
复制

在上面的示例中,定义了普通的User实体对象。需要注意的是,实体类对象必须继承Serializable序列化接口,否则会报数据无法序列化的错误。

4.2.2 定义消费者

修改Consumer类,将参数换成User对象。示例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class Consumer {
  @RabbitHandler
  @RabbitListener(queuesToDeclare = @Queue("rabbitmq_queue_object"))
  public void process(User user) {
    System.out.println("消费者消费消息111user=====name:" + user.getName()+",password:"+user.getPassword());
  
  }
}
代码语言:javascript
代码运行次数:0
运行
复制

其实,消费者类和消息处理方法和之前的类似,只不过将参数换成了实体对象,监听rabbitmq_queue_object队列。

4.2.3 定义生产者

修改Producer类,定义User实体对象,并通过convertAndSend方法发送对象消息。示例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class Producer {
  @Autowired
  private RabbitTemplate rabbitTemplate;
  
  public void produce() { 
    User user=new User();
    user.setName("weiz");
    user.setPassword("123456");
    System.out.println("生产者生产消息111=====" + user);
    
    rabbitTemplate.convertAndSend("rabbitmq_queue_object", user);
  }
}
代码语言:javascript
代码运行次数:0
运行
复制

在上面的示例中,还是调用convertAndSend()方法发送实体对象。convertAndSend()方法支持String、Integer、Object等基础的数据类型。

4.2.4 验证测试

创建单元测试类,注入生产者对象,然后调用produceObj()方法发送实体对象消息,从而验证消息能否被成功接收。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
  @Autowired
  Producer producer;
  @Test
  public void testProduceObj() throws InterruptedException {
    producer.produceObj();
    Thread.sleep(1*1000);
  }
}
代码语言:javascript
代码运行次数:0
运行
复制

最后,单击Run Test或在方法上右击,选择Run 'contextLoads()',运行单元测试程序,查看后台输出情况,运行结果如下图所示。

通过上面的示例成功实现了RabbitMQ发送和接收实体对象,使得消息的数据结构更加清晰,也更加贴合面向对象的编程思想。

最后

以上,我们就把消息队列介绍完了。消息中间件在互联网公司使用得越来越多,希望大家能够熟悉其使用。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022/06/13 17:06:22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师精进 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
SpringCloud-基于SpringAMQP实现消息队列
Spring AMQP作为Spring框架的一部分,是一套用于支持高级消息队列协议(AMQP)的工具。AMQP是一种强大的消息协议,旨在支持可靠的消息传递,特别适用于构建分布式系统。Spring AMQP构建在RabbitMQ之上,提供了在微服务架构中进行异步通信和消息传递的强大机制。
Damon小智
2024/03/10
2690
SpringCloud-基于SpringAMQP实现消息队列
SpringBoot整合RabbitMQ 实现五种消息模型 详细教程
今天说下了消息队列中间件,各种队列性能对比,RabbitMQ队列,交换机(Exchange)以及消息 中间件的应用场景,然后带着大家一起实现RabbitMQ的五种消息模型。
全栈程序员站长
2022/08/28
1.2K0
SpringBoot整合RabbitMQ 实现五种消息模型 详细教程
高性能消息队列中间件MQ_part2
之前我们使用原生JAVA操作RabbitMQ较为繁琐,接下来我们使用SpringBoot整合RabbitMQ,简化代码编写。
天天Lotay
2023/02/16
4420
高性能消息队列中间件MQ_part2
Spring Boot:使用Rabbit MQ消息队列
消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息,对消息队列有读权限的进程则可以从消息队列中读走消息,而消息队列就是在消息的传输过程中保存消息的容器,你可以简单的把消息队列理解为类似快递柜,快递员(消息发布者)往快递柜(消息队列)投递物件(消息),接受者(消息订阅者)从快递柜(消息队列)接收物件(消息),当然消息队列往往还包含一些特定的消息传递和接收机制。
朝雨忆轻尘
2019/07/04
2.2K0
Spring Boot:使用Rabbit MQ消息队列
玩转 Spring Boot 集成篇(RabbitMQ)
MQ 经常被应用于流量削峰、异步消息、应用解耦,常见的 MQ 开源组件有 RabbitMQ、Kafka、ActiveMQ、RocketMQ 等。
一猿小讲
2022/02/25
8.5K0
玩转 Spring Boot 集成篇(RabbitMQ)
spring-boot-route(十三)整合RabbitMQ消息队列
这篇是SpringBoot整合消息队列的第一篇文章,我们详细介绍下消息队列的相关内容。
Java旅途
2020/10/21
8430
spring-boot-route(十三)整合RabbitMQ消息队列
【Spring云原生系列】Spring RabbitMQ:异步处理机制的基础--消息队列 原理讲解+使用教程
于是坤坤转念一想 天下女神千千万 何必单恋一枝花? 他提出了这样一个理论“只要舔的够多 够快 总能成功的” 于是他转换策略 他决定在列表中循环
苏泽
2024/03/10
6970
【Spring云原生系列】Spring RabbitMQ:异步处理机制的基础--消息队列 原理讲解+使用教程
RabbitMQ从概念到使用、从Docker安装到RabbitMQ整合Springboot【1.5w字保姆级教学】
我们先来聊聊消息中间件: 消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。(来自百度百科)
掉发的小王
2022/07/11
5030
RabbitMQ从概念到使用、从Docker安装到RabbitMQ整合Springboot【1.5w字保姆级教学】
一起来学SpringBoot | 第十二篇:初探RabbitMQ消息队列
MQ全称(MessageQueue)又名消息队列,是一种异步通讯的中间件。可以将它理解成邮局,发送者将消息传递到邮局,然后由邮局帮我们发送给具体的消息接收者(消费者),具体发送过程与时间我们无需关心,它也不会干扰我进行其它事情。常见的MQ有 kafka、 activemq、 zeromq、 rabbitmq 等等,各大MQ的对比和优劣势可以自行 Google
battcn
2018/08/03
6470
【消息队列】RabbitMQ如何保障消息可靠性投递
消息队列的八股文最喜欢问这个。消息可靠性投递,这个对于消息队列非常重要,很多时候,我们不是人为的去干预,但是仍然出现其他意外的事情。
千羽
2024/06/05
2800
【消息队列】RabbitMQ如何保障消息可靠性投递
详解SpringCloud中RabbitMQ消息队列原理及配置,一篇就够!
公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。
java进阶架构师
2020/09/22
3.7K0
详解SpringCloud中RabbitMQ消息队列原理及配置,一篇就够!
消息队列-RabbitMQ
交换机有四种类型:direct exchange、topic exchange、fanout exchange、headers exchange。
lpe234
2021/03/04
1.7K0
入门rabbitmq看这个就够了
Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台
Java鱼头
2022/09/08
5910
入门rabbitmq看这个就够了
springboot(八):RabbitMQ详解
RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用。 消息中间件在互联网公司的使用中越来越多,刚才还看到新闻阿里将RocketMQ捐献给了apache,当然了今天的主角还是讲RabbitMQ。消息中间件最主要的作用是解耦,中间件最标准的用法是生产者生产消息传送到队列,消费者从队列中拿取消息并处理,生产者不用关心是谁来消费,消费者不用关心谁在生产消息,从而达到解耦的目的。在分布式的系统中,消息队列也会被用在很多其它的方面,比如:分布式事务的支持,RPC的
纯洁的微笑
2018/04/18
1.1K0
springboot(八):RabbitMQ详解
【云原生进阶之PaaS中间件】第四章RabbitMQ-1-简介及工作模式
RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。AMQP(Advanced Message Queue:高级消息队列协议)它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。RabbitMQ 最初起源于消息系统,用于在分布式系统中存储转发消息,具体有如下一些特点:
江中散人_Jun
2024/02/18
4130
【云原生进阶之PaaS中间件】第四章RabbitMQ-1-简介及工作模式
【SpringBoot2.0系列09】SpringBoot之rabbitmq使用实现
RabbitMQ是由Erlang语言编写的实现了高级消息队列协议(AMQP)的开源消息代理软件(也可称为 面向消息的中间件)。支持Windows、Linux/Unix、MAC OS X操作系统和包括JAVA在内的多种编程语言。
yukong
2018/09/03
1.2K0
【SpringBoot2.0系列09】SpringBoot之rabbitmq使用实现
Spring Boot(八):RabbitMQ 详解
RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用。
纯洁的微笑
2019/05/22
8800
消息中间件之Rabbitmq
1、https://www.kancloud.cn/yunxifd/rabbitmq/96997
爱撒谎的男孩
2019/12/31
9470
SpringCloud-MQ消息队列
MQ (MessageQueue) ,中文是消息队列,字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。消息队列是一种基于生产者-消费者模型的通信方式,通过在消息队列中存放和传递消息,实现了不同组件、服务或系统之间的异步通信。
Damon小智
2024/03/03
3940
SpringCloud-MQ消息队列
ActiveMQ、RabbitMQ 和 Kafka 在 Spring Boot 中的实战
在现代的微服务架构和分布式系统中,消息队列 是一种常见的异步通信工具。消息队列允许应用程序之间通过 生产者-消费者模型 进行松耦合、异步交互。在 Spring Boot 中,我们可以通过简单的配置来集成不同的消息队列系统,包括 ActiveMQ、RabbitMQ 和 Kafka。本文将重点介绍它们的实战案例及使用时需要注意的地方。
井九
2024/10/12
3280
ActiveMQ、RabbitMQ 和 Kafka 在 Spring Boot 中的实战
推荐阅读
相关推荐
SpringCloud-基于SpringAMQP实现消息队列
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验