消息队列MQ

文章目录

  • 同步通讯和异步通讯
  • 什么是MQ?
  • 一.RabbitMQ概述
  • 二.SpringAMQP
    • 1.Work Queue 工作队列
    • 2.发布订阅-Fanout Exchange
    • 3.发布订阅-DirectExchange
    • 4.发布订阅-TopicExchange
  • 3.消息转换器


同步通讯和异步通讯

其实在之前的JAVASE中就已经在线程一章中接触过了同步和异步的概念,那么同步通讯和异步通讯有什么异同呢?

1.时序(Timing):
同步通讯: 在同步通讯中,发送方发出请求后会等待接收方的响应,直到接收到响应或者发生超时。这意味着发送和接收两个操作是顺序执行的。
异步通讯: 在异步通讯中,发送方发送消息后不会等待接收方的响应,而是继续执行其他操作。接收方在接收到消息后会进行处理,但发送方不会阻塞等待。

2.阻塞(Blocking):
同步通讯: 在同步通讯中,发送方通常会被阻塞,直到接收到响应或者发生超时。这意味着发送方需要等待,直到接收方完成处理。
异步通讯: 在异步通讯中,发送方通常不会被阻塞,可以继续执行其他任务。这使得异步通讯适用于需要同时处理多个任务的场景。

3.响应方式(Response):
同步通讯: 在同步通讯中,发送方需要等待接收方的响应,响应通常是直接返回给发送方的。
异步通讯: 在异步通讯中,发送方不会直接等待接收方的响应。通常使用回调函数、事件或者轮询等方式来处理接收方的响应。

4.可靠性(Reliability):
同步通讯: 由于同步通讯需要等待接收方的响应,所以相对容易处理错误和异常情况,可以更容易地实现重试机制。
异步通讯: 异步通讯中,由于发送方不等待响应,错误处理可能更为复杂,需要采用其他机制来处理错误,例如超时处理、回调错误处理等。

5.适用场景(Use Cases):
同步通讯: 适用于简单的请求-响应场景,例如传统的函数调用、HTTP 请求等。
异步通讯: 适用于需要提高系统的并发性、响应性和吞吐量的场景,例如事件驱动架构、消息队列系统等。


同步调用存在的问题
在这里插入图片描述

总而言之,同步调用的优点:时效性较强,可以立即得到结果
同步调用的问题:1.耦合度高2.性能和吞吐能力下降3.有额外的资源消耗4.有级联失败问题


异步调用方案

异步调用常见实现就是事件驱动模式

事件驱动优势:

优势一:服务解耦

当后期想要增加服务,不需要与服务调用者打交道, 只需要订阅事件到Broker(消息队列即可)
在这里插入图片描述


优势二:性能提升,吞吐量提高

当来自网关的请求调用到了服务,这个服务需要调用其他服务时,只需要通知相应的消息队列即可,服务耗时减少,其次,由于消息队列采用的是异步通讯,所以耗时相应减少

在这里插入图片描述


优势三:服务没有强依赖,不担心级联失败问题

当消息队列的某个服务阻塞后,也不影响整个消息的通知以及其他服务和消息队列的阻塞
在这里插入图片描述


优势四:流量削峰

当有高并发请求时,消息队列可以分批次发送消息,进行流量削峰

在这里插入图片描述

总结:
异步通信的优点:

  • 耦合度低

  • 吞吐量提升

  • 故障隔离

  • 流量削峰

异步通信的缺点:

  • 依赖于Broker的可靠性、安全性、吞吐能力

  • 架构复杂了,业务没有明显的流程线,不好追踪管理


什么是MQ?

MQ (MessageQueue),中文是消息队列,字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。

市面上常见的MQ对比:

在这里插入图片描述

一.RabbitMQ概述

RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)

RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。

安装: 通过Docker镜像安装即可


RabbitMQ的结构和概念

在这里插入图片描述

RabbitMQ中的几个概念:

channel:操作MQ的工具

exchange:路由消息到队列中

queue:缓存消息

virtual host:虚拟主机,是对queue、exchange等资源的逻辑分组


常见消息模型

MQ的官方文档中给出了5个MQ的Demo示例,对应了几种不同的用法:

基本消息队列(BasicQueue)

工作消息队列(WorkQueue)

在这里插入图片描述
发布订阅(Publish、Subscribe),又根据交换机类型不同分为三种:

Fanout Exchange:广播

Direct Exchange:路由

Topic Exchange:主题
在这里插入图片描述

由于使用官网提供的api编写代码操作RabbitMQ过于复杂,下面引出SpringAMQP

二.SpringAMQP

什么是SpringAMQP?
在这里插入图片描述


案例:利用SpringAMQP实现HelloWorld中的基础消息队列功能

流程如下:

1.在父工程中引入spring-amqp的依赖

因为publisher和consumer服务都需要amqp依赖,因此这里把依赖直接放到父工程mq-demo中:

		<!--AMQP依赖,包含RabbitMQ-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

2.在publisher服务中利用RabbitTemplate发送消息到simple.queue这个队列
在这里插入图片描述

3.在consumer服务中编写消费逻辑,绑定simple.queue这个队列
在这里插入图片描述

总结:
1.SpringAMQP如何发送消息?

  • 引入amqp的starter依赖

  • 配置RabbitMQ地址

  • 利用RabbitTemplate的convertAndSend方法

2.SpringAMQP如何接收消息?

  • 引入amqp的starter依赖

  • 配置RabbitMQ地址

  • 定义类,添加@Component注解

  • 类中声明方法,添加@RabbitListener注解,方法参数就时消息

注意:消息一旦消费就会从队列删除,RabbitMQ没有消息回溯功能


1.Work Queue 工作队列

Work queue工作队列,可以提高消息处理速度,避免队列消息堆积

在这里插入图片描述

消费预取限制(能者多劳)

修改application.yml文件,设置preFetch这个值,可以控制预取消息的上限:

在这里插入图片描述


发布( Publish )、订阅( Subscribe )

发布订阅模式与之前案例的区别就是允许将同一消息发送给多个消费者。实现方式是加入了exchange(交换机)

常见exchange类型包括:

  • Fanout:广播

  • Direct:路由

  • Topic:话题

在这里插入图片描述


2.发布订阅-Fanout Exchange

Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue

在这里插入图片描述

使用方法:

案例:利用SpringAMQP演示FanoutExchange的使用

实现思路如下:

1.在consumer服务中,利用代码声明队列、交换机,并将两者绑定

@Configuration
public class FanoutConfig {
    //声明FanoutExchange交换机
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("root.fanout");
    }
    //声明第一个队列
    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1");
    }
    //绑定队列一和交换机
    @Bean
    public Binding bindingQueue1(Queue fanoutQueue1,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }
    //声明第二个队列
    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }
    //绑定队列二和交换机
    @Bean
    public Binding bindingQueue2(Queue fanoutQueue2,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
}

2.在consumer服务中,编写两个消费者方法,分别监听fanout.queue1和fanout.queue2

@Component
public class SpringRabbitListener {
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueueMessage(String msg) {
        System.out.println("spring 消费者接收到消息 :【" + msg + "】");
    }
    @RabbitListener(queues = "fanout.queue1")
    public void listenFanoutQueue1(String msg){
        System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
    }
    @RabbitListener(queues = "fanout.queue2")
    public void listenFanoutQueue2(String msg){
        System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
    }
}

3.在publisher中编写测试方法,向itcast.fanout发送消息

@Test
    void testFanoutExchange() {
        // 队列名称
        String exchangeName = "root.fanout";
        // 消息
        String message = "hello, everyone!";

        rabbitTemplate.convertAndSend(exchangeName,"",message);
    }

Q&A
1.交换机的作用是什么?

  • 接收publisher发送的消息

  • 将消息按照规则路由到与之绑定的队列

  • 不能缓存消息,路由失败,消息丢失

  • FanoutExchange的会将消息路由到每个绑定的队列

2.声明队列、交换机、绑定关系的Bean是什么?

  • Queue

  • FanoutExchange

  • Binding


3.发布订阅-DirectExchange

Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为路由模式(routes)。

每一个Queue都与Exchange设置一个BindingKey

发布者发送消息时,指定消息的RoutingKey

Exchange将消息路由到BindingKey与消息RoutingKey一致的队列

在这里插入图片描述

案例:利用SpringAMQP演示DirectExchange的使用

实现思路如下:

1.利用@RabbitListener声明Exchange、Queue、RoutingKey并且同时实现监听direct.queue1和direct.queue2

@RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue1"),
            exchange = @Exchange(name = "root.direct",type = ExchangeTypes.DIRECT),
            key = {"red","blue"}
    ))
    public void listenDirectQueue1(String msg){
        System.out.println("消费者1接收到Direct消息:【"+msg+"】");
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue2"),
            exchange = @Exchange(name = "root.direct",type = ExchangeTypes.DIRECT),
            key = {"red","yellow"}
    ))
    public void listenDirectQueue2(String msg){
        System.out.println("消费者2接收到Direct消息:【"+msg+"】");
    }

2.在publisher中编写测试方法,向itcast. direct发送消息

@Test
    void testDirectExchange() {
        // 队列名称
        String exchangeName = "root.direct";
        // 消息
        String message = "红色警报!日本乱排核废水,导致海洋生物变异,惊现哥斯拉!";
        // 发送消息,参数依次为:交换机名称,RoutingKey,消息
        rabbitTemplate.convertAndSend(exchangeName,"red",message);
    }

Q&A
1.描述下Direct交换机与Fanout交换机的差异?

  • Fanout交换机将消息路由给每一个与之绑定的队列

  • Direct交换机根据RoutingKey判断路由给哪个队列

  • 如果多个队列具有相同的RoutingKey,则与Fanout功能类似

2.基于@RabbitListener注解声明队列和交换机有哪些常见注解?

  • @Queue

  • @Exchange


4.发布订阅-TopicExchange

TopicExchange与DirectExchange类似,区别在于routingKey必须是多个单词的列表,并且以 . 分割。

Queue与Exchange指定BindingKey时可以使用通配符

  • #:代指0个或多个单词

  • *:代指一个单词

在这里插入图片描述

区别在于Topic交换机接收的消息RoutingKey必须是多个单词,以 . 分割

在这里插入图片描述


3.消息转换器

在SpringAMQP的发送方法中,接收消息的类型是Object,也就是说我们可以发送任意对象类型的消息,SpringAMQP会帮我们序列化为字节后发送。

Spring的对消息对象的处理是由org.springframework.amqp.support.converter.MessageConverter来处理的。而默认实现是SimpleMessageConverter,基于JDK的ObjectOutputStream完成序列化。如果要修改只需要定义一个MessageConverter 类型的Bean即可。推荐用JSON方式序列化,步骤如下:
在这里插入图片描述
在这里插入图片描述

总结:SpringAMQP中消息的序列化和反序列化是怎么实现的?

  • 利用MessageConverter实现的,默认是JDK的序列化
  • 注意发送方与接收方必须使用相同的MessageConverter

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/196622.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实战:登录接口测试用例举例

以下是一些可能的登录接口测试用例&#xff08;使用Python编写的&#xff09;&#xff1a; 1. 测试正常情况下的登录接口&#xff1a; # 请求URL url "https://example.com/api/login" # 请求参数 username "testuser" password "testpassword&q…

数据治理框架和成熟度模型

数据治理成熟度模型 一个企业的数据治理能力越高&#xff0c;所享受到数据治理带来的价值也会越多&#xff0c;如增加收入、减少成本、降低风险等。于是&#xff0c;很多企业想要准确地评估本公司的数据治理能力&#xff0c;可以利用数据治理成熟度模型方法&#xff0c;包括 D…

摄影网站的技术 SEO:提示和最佳实践

摄影就是要给人留下良好的第一印象。如果你想在竞争中领先&#xff0c;摄影师的SEO是您可以采用的最佳营销方法之一。 我们都曾有过这样的经历&#xff1a;你建立了一个漂亮的作品集网站来吸引更多的业务。网站上线并在社交媒体上推广后&#xff0c;您就可以坐等了。网站访问量…

堆的应用(堆排序、Top-K问题)

文章目录 1 堆排序2 Top-K问题 1 堆排序 堆排序是一种基于二叉堆&#xff08;通常使用数组实现&#xff09;的排序算法。 它的基本思想是利用堆这种数据结构的性质&#xff0c;通过建立一个堆&#xff08;大堆或小堆&#xff09;&#xff0c;使得堆的根节点是所有节点中的最大值…

牛客 算法题 golang语言实现

题目 HJ101 输入整型数组和排序标识&#xff0c;对其元素按照升序或降序进行排序 描述 输入整型数组和排序标识&#xff0c;对其元素按照升序或降序进行排序数据范围&#xff1a; 1 ≤ &#xfffd; ≤ 10001≤n≤1000 &#xff0c;元素大小满足 0 ≤ &#xfffd; &#…

提升企业网络安全的得力助手——EventLog Analyzer网络日志管理

在当今数字化时代&#xff0c;企业的网络安全问题变得尤为重要。为了更好地应对日益增多的威胁和安全漏洞&#xff0c;企业需要一种高效的网络日志管理工具&#xff0c;EventLog Analyzer便是其中一款卓越的解决方案。 EventLog Analyzer EventLog Analyzer是一款综合性的网络…

探索短剧市场的商机:打造短视频平台的全方位指南

目前短剧市场蓬勃发展&#xff0c;上半年备案数远超电视剧&#xff0c;彰显了短剧小程序市场潜力巨大&#xff0c;商业价值巨大。用户对短小精悍娱乐内容的需求不断增加&#xff0c;而新兴市场中有限的短剧小程序正好能够迎合这一需求。 搭建短视频平台的关键步骤&#xff1a; …

GOAT:多模态、终身学习、平台无关的机器人通用导航系统

机器人应用中涉及到的核心技术包括&#xff1a;环境感知与理解、实时定位与建图、路径规划、行为控制等。GOAT通过多模态结合终生学习的方式让你的机器人可以在未知环境中搜索和导航到任何物体。小白也可以零门槛上手。 项目地址&#xff1a;https://theophilegervet.github.i…

性能优化的一般策略及方法

性能优化的一般策略及方法 在汽车嵌入式开发领域&#xff0c;性能优化始终是一个无法回避的问题&#xff1a; 座舱 HMI 想要实现更流畅的人机交互 通信中间件在给定的 CPU 资源下&#xff0c;追求更高的吞吐量 更一般的场景&#xff1a;嵌入式设备 CPU 资源告急&#xff0c;需…

Web前端开发技术:图像与多媒体文件

在现代的Web开发中&#xff0c;图像和多媒体文件在各种网站和应用程序中扮演着至关重要的角色。它们不仅能提供更丰富的内容&#xff0c;还能大大提高应用程序的吸引力和用户体验。本文将深入介绍一些关键的Web前端开发技术&#xff0c;这些技术将有助于开发者在处理图像和多媒…

【Python3】【力扣题】367. 有效的完全平方数

【力扣题】题目描述&#xff1a; 【Python3】代码&#xff1a; 1、解题思路&#xff1a;Python函数。num的平方根 或者 num的0.5次幂。 知识点&#xff1a;float.is_integer(...)&#xff1a;判断浮点数的值是否等于整数。也可以&#xff1a;浮点数.is_integer()。 pow(a,b)&…

JAVA多线程总结

一、概念&#xff1a; 1、什么是多任务 多任务就是在同一时间做多件事情&#xff0c;如边吃饭边玩手机等。看起来是多个任务都在做&#xff0c;本质上我们的大脑在同一时间依旧只做了一件件事情 2、什么是程序 程序是指令和数据的有序集合&#xff0c;其本身没有任…

“一键转换JPG到BMP:轻松优化图片管理的革命性工具“

亲爱的用户们&#xff0c;您是否曾经因为图片格式不兼容而感到烦恼&#xff1f;是否曾经为了转换图片格式而耗费大量时间&#xff1f;现在&#xff0c;我们为您带来了一款全新的图片转换工具&#xff0c;它可以轻松解决您的问题&#xff01; 首先&#xff0c;我们进入首助编辑高…

同旺科技 USB 转 RS-485 适配器 -- 隔离型

内附链接 1、USB 转 RS-485 适配器 隔离版主要特性有&#xff1a; ● 支持USB 2.0/3.0接口&#xff0c;并兼容USB 1.1接口&#xff1b; ● 支持USB总线供电&#xff1b; ● 支持Windows系统驱动&#xff0c;包含WIN10 / WIN11 系统32 / 64位&#xff1b; ● 支持Windows …

idea打开.class文件没有反编译

1 问题描述 新安装的idea开发工具&#xff0c;打开.class文件查看内容时发现没有将文件进行反编译&#xff0c;所以具体的代码实现看不到。如图所示&#xff1a; 尝试了各种办法解决&#xff0c;最终都没有解决我的问题&#xff0c;其他同事的idea开发工具都可以打开.class文件…

基于SpringBoot与Vue的增城高校二手物品交易系统

基于SpringBoot 与 Vue 的增城高校二手物品交易系统的设计与实现 摘要&#xff1a;随着生活水平和在校大学生消费能力的提高&#xff0c;学生用品的迭代速度越来越快&#xff0c;导致大量的闲置物品无法及时完成处理&#xff0c;而传统的线下摆摊等方式处理不仅效率低&#xf…

Java-认识异常

本章重点&#xff1a; 1. 异常概念与体系结构 2. 异常的处理方式 3. 异常的处理流程 4. 自定义异常类 1. 异常的概念与体系结构 1.1 异常的概念 在Java中&#xff0c;将程序执行过程中发生的不正常行为称为异常。比如之前写代码时经常遇到的&#xff1a; 1. 算术异常 2. 数组…

详解STL库—map和set

目录 一、关联式容器 二、键值对 SGI-STL中关于键值对的定义&#xff1a; 三、set 3.1 set的介绍 3.2 set的使用 1.set的模板参数列表​编辑 2. set的构造 3. set的迭代器 4. set的容量 5. set修改操作 6. set的使用举例 四、map 4.1map的介绍 4.2 map的使用 1…

揭秘!9个月完成亚运会的整体数字化观测

项目背景与业务场景 2023 第 19 届亚运会在杭州举办&#xff0c;这将提高杭州的国际知名度&#xff0c;促进杭州经济、社会的全面发展&#xff0c;并将进一步推动奥林匹克运动在中国的发展&#xff0c;并且提升杭州城市形象和国际影响力。为亚运村村民提供便捷周到的服务和丰富…

【NI-RIO入门】为CompactRIO供电

在大多数情况下&#xff0c;您可以使用可直接连接系统的电源&#xff0c;例如墙上的电源插座。但是&#xff0c;某些应用程序或环境缺乏可用电源&#xff0c;您必须使用其他电源&#xff0c;例如电池。无论您是否有可用电源&#xff0c;您可能都希望通过为系统提供一些冗余来确…