SpringCloud(五)MQ消息队列

news/2024/4/26 18:16:28/文章来源:https://blog.csdn.net/Louie_min/article/details/129239508

MQ

  • 概念
  • 常见消息模型
    • helloworld案例
      • 实现
        • 实现spring AMQP发送消息
        • 实现spring AMQP接收消息
    • 工作消息队列
      • 实现
    • 发布订阅模型
      • Fanout Exchange
        • 实现
      • DirectExchange
        • 实现
      • TopicExchange
        • 实现
      • DirectExchange 和FanoutExchange的差异
      • DirectExchange 和TopicExchange的差异
    • 基于@RabbitListener注解声明队列有 哪些常用注
  • 消息转换器
    • 注意
  • 同步调用
  • 异步调用
  • 安装
  • SpringAMQP
    • 特征

概念

MQ(MessageQueue):消息队列,事件驱动架构中的Broker
在这里插入图片描述

  • channel:操作MQ的工具
  • exchange:路由消息到队列
  • queue:缓存消息
  • virtual host: 虚拟主机,是对queue、exchange等资源逻辑分组

常见消息模型

在这里插入图片描述在这里插入图片描述

helloworld案例

角色:

  • publisher:消息发布者,将消息发送到队列queue
  • queue:消息队列,负责接受并缓存消息
  • consumer:订阅队列,处理队列中的消息
    在这里插入图片描述

实现

实现spring AMQP发送消息

  • 在父工程引入spring-amqp的依赖
        <!--AMQP依赖,包含RabbitMQ--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
  • 在publisher服务中利用RabbitTemplate发送消息到simple.queue这个队列

    • 在publisher服务中编写application.yml,添加mq连接信息
    spring:rabbitmq:host: 127.0.0.1port: 5672virtual-host: /username: rootpassword: toor
    
    • 在publisher服务中新建一个测试类,编写测试方法
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringAmqpTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void testSimpleQueue(){String queueName = "simple.queue";String message = "hello,spring amqp!";rabbitTemplate.convertAndSend(queueName,message);}
    }
    

实现spring AMQP接收消息

  • 在父工程引入spring-amqp的依赖
        <!--AMQP依赖,包含RabbitMQ--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
  • 在consumer服务中编写消费逻辑,监听simple.queue。

    • 在consumer服务中编写application.yml,添加mq连接信息
    spring:rabbitmq:host: 127.0.0.1port: 5672virtual-host: /username: rootpassword: toor
    
    • 在publisher服务中新建一个测试类,编写测试方法
    @Component
    public class SpringRabbitListener {@RabbitListener(queues = "simple.queue")public void listenSimpleQueueMessage (String msg) throws InterruptedException{System.out.println("spring 消费者接收到消息:【"+msg+"】");}
    }

工作消息队列

作用: 提高消息处理速度,避免队列消息堆积。
在这里插入图片描述

实现

  1. 在publisher服务中定义测试方法,每秒产生50条消息,发送到simple.queue
	  @Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void testWorkQueue() throws InterruptedException {String queueName = "simple.queue";String message = "hello,spring amqp!";for (int i = 0; i <= 50; i++) {rabbitTemplate.convertAndSend(queueName,message+i);Thread.sleep(20);}}
  1. 在consumer服务中定义两个消息监听者,都监听simple.queue队列
    @RabbitListener(queues = "simple.queue")public void listenWorkQueueMessage1 (String msg) throws InterruptedException{System.out.println("spring 消费者1接收到消息:【"+msg+"】");Thread.sleep(20);}@RabbitListener(queues = "simple.queue")public void listenWorkQueueMessage2 (String msg) throws InterruptedException{System.err.println("spring 消费者1接收到消息:【"+msg+"】");//err输出为红色Thread.sleep(200);
  1. 消费者1每秒处理50条消息,消费者2每秒处理10条消息
    • 修改application.yml文件,设置preFetch这个值,可以控制预取消息的上限
spring:rabbitmq:host: 127.0.0.1port: 5672virtual-host: /username: rootpassword: toorlistener:direct:prefetch: 1

发布订阅模型

概念: 与之前模型区别是,允许将同一消息发送给多个消费者。
实现方式: exchange(交换机)
exchange: 负责消息路由,不存储,路由失败则消息丢失
常见exchange类型

  • Fanout:广播
  • Direct:路由
  • Topic:话题

在这里插入图片描述

Fanout Exchange

Fanout Exchange:将接收到的消息路由到每一个跟其绑定的queue

实现

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

    1. SringAMQP提供了声明交换机、队列、绑定关系的API。
      在这里插入图片描述
    2. 在consumer服务常见一个类,添加@configuration注解,并声明FanoutExchange、Queue和绑定关系对象Binding。
    @Configuration
    public class FanoutConfig {//声明FanoutExchange交换机@Beanpublic FanoutExchange fanoutExchange(){return new FanoutExchange("root.fanout");}//声明第一个队列@Beanpublic Queue fanoutQueue1(){return new Queue("fanout.queue1");}//绑定队列1和交换机@Beanpublic Binding bindingQueue1(Queue fanoutQueue1,FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);}
    //第二个同第一个
    }
    
  2. 在consumer服务中,编写两个消费者方法,分别监听fanout.queue1和fanout.queue2

    @RabbitListener(queues = "fanout.queue1")public void listenFanoutQueue1Message (String msg) throws InterruptedException{System.out.println("spring 消费者接收到消息:【"+msg+"】");}@RabbitListener(queues = "fanout.queue2")public void listenFanoutQueue2Message (String msg) throws InterruptedException{System.out.println("spring 消费者接收到消息:【"+msg+"】");}
  1. 在publisher中编写测试方法,向root.fanout发送消息
    @Testpublic void testSendFanoutExchange(){String exchangeName = "root.fanout";String message = "hello,spring amqp!";rabbitTemplate.convertAndSend(exchangeName,message);}

DirectExchange

DirectExchange: 将接收到的消息更具规则路由到指定的Queue,因此称为路由模式(routes)

  • 每一个Queue都与Exchange设置一个BindingKey
  • 发布者发送消息时,指定消息的RoutingKey
  • Exchange将消息路由到BindingKey与消息RoutingKey一致的队列
    在这里插入图片描述

实现

  1. 利用@RabbitListener声明Exchange、Queue、RoutingKey
  2. 在consumer服务中编写两个消费者方法,分别监听direct.queue1和direct.queue2
    @RabbitListener(bindings = @QueueBinding(value = @Queue(name="direct.queue1"),exchange = @Exchange(name = "root.direct",type = ExchangeTypes.DIRECT),key = {"red","yellow"}))public void listenDirectQueue1Message (String msg) throws InterruptedException{System.out.println("spring 消费者接收到direct.queue1的消息:【"+msg+"】");}@RabbitListener(bindings = @QueueBinding(value = @Queue(name="direct.queue2"),exchange = @Exchange(name = "root.direct",type = ExchangeTypes.DIRECT),key = {"red","yellow"}))public void listenDirectQueue2Message (String msg) throws InterruptedException{System.out.println("spring 消费者接收到direct.queue2的消息:【"+msg+"】");}
  1. 在publisher中编写测试方法,向root.direct发送消息
    @Testpublic void testSendDirectExchange(){String exchangeName = "root.direct";String message = "hello,red!";rabbitTemplate.convertAndSend(exchangeName,"red",message);}

TopicExchange

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

Queue与Exchange指定BindingKey时可以使用通配符
# :代指0个或多个单词
*:代指一个单词
在这里插入图片描述

实现

  1. 利用@RabbitListener声明Exchange、Queue、RoutingKey
  2. 在consumer服务中编写两个消费者方法,分别监听topic.queue1和topic.queue2
    @RabbitListener(bindings = @QueueBinding(value = @Queue(name="topic.queue1"),exchange = @Exchange(name = "root.topic",type = ExchangeTypes.TOPIC),key = "china.#"))public void listenTopicQueue1Message (String msg) throws InterruptedException{System.out.println("spring 消费者接收到topic.queue1的消息:【"+msg+"】");}@RabbitListener(bindings = @QueueBinding(value = @Queue(name="topic.queue2"),exchange = @Exchange(name = "root.topic",type = ExchangeTypes.TOPIC),key = "#.news"))public void listenTopicQueue2Message (String msg) throws InterruptedException{System.out.println("spring 消费者接收到topic.queue2的消息:【"+msg+"】");}
  1. 在publisher中编写测试方法,向root.topic发送消息
    @Testpublic void testSendTopicExchange(){String exchangeName = "root.topic";String message = "hello,china.news!";rabbitTemplate.convertAndSend(exchangeName,"china.news",message);}

DirectExchange 和FanoutExchange的差异

  • FanoutExchange将消息路由给每一个与之绑定的队列
  • DirectExchange根据RoutingKey判断路由给哪个队列
  • 如果多个队列具有相同的RoutingKey,则与Fanout功能类似

DirectExchange 和TopicExchange的差异

  • TopicExchange的routineKey必须使用多个单词,以== . ==分割
  • TopicExchange可以使用通配符

基于@RabbitListener注解声明队列有 哪些常用注

  • @Queue
  • @Exchange

消息转换器

设置JSON方式序列化
发送消息

  • 在publisher服务引入依赖
<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>2.9.10</version>
</dependency>
  • 在publisher服务声明MessageConverter
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;@Beanpublic MessageConverter jsonMessageConverter(){return new Jackson2JsonMessageConverter();}

接收消息

  • 在consumer服务引入依赖
<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>2.9.10</version>
</dependency>
  • 在consumer服务声明MessageConverter
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;@Beanpublic MessageConverter jsonMessageConverter(){return new Jackson2JsonMessageConverter();}
  • 定义消费者
    @RabbitListener(queues = "object.queue")public void listenObjectQueueMessage(Map<String,Object> msg){System.err.println("spring 消费者1接收到消息:【"+msg+"】");//err输出为红色}

注意

MessageConverter默认是JDK序列化
接收方和发送方必须使用相同的MessageConverter

同步调用

优点: 时效性高
问题:

  • 耦合度高
  • 性能下降
  • 资源浪费
  • 级联失败

异步调用

实现方式:

  • 事件驱动(常用)

优势:

  • 服务解耦
  • 性能提升,吞吐量提高
  • 故障隔离。没有强依赖,不担心级联失败问题
  • 流量削锋

缺点:

  • 依赖Broker的可靠性、安全性、吞吐能力
  • 架构复杂、业务没有明显的流程线,不好追踪管理

安装

docker pull rabbitmq:3-managementdocker run \-e RABBITMQ_DEFAULT_USER=root \-e RABBITMQ_DEFAULT_PASS=toor \--name mq \--hostname mq1 \-p 15672:15672 \-p 5672:5672 \-d \rabbitmq:3-management

SpringAMQP

AMQP(Advance Message Queuing Protocol):是用于在应用程序或之间传递业务消息的开放标准,该协议与语言平台无关,更符合微服务中独立性的要求

Spring AMQP: 是基于AMQP协议定义的一套API规范,提供了模板来发送和接收消息。包含两部分:

  • spring-amqp:基础抽象
  • spring-rabbit:底层默认实现

特征

  • 监听器容器,用于异步处理入站消息
  • 用于发送和接收消息的RabbitTemplate
  • RabbitAdmin用于自动声明队列、交换和绑定

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

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

相关文章

钉钉产品体验报告

一、调研的目的了解企业社交软件&#xff0c;借写竞品分析来帮助自己整理思路&#xff0c;看清市场的发展趋势&#xff1b;体验这类企业设计软件&#xff0c;掌握产品核心业务流程和产品结构&#xff0c;把握需求对应的功能点和界面结构&#xff0c;并侧面了解用户习惯&#xf…

用Python做数据分析有哪些优势?

众所周知&#xff0c;可以用作数据分析的语言有很多&#xff0c;包含Python、R语言等&#xff0c;而且Python被誉为数据分析的一大利器&#xff0c;更是该领域的首选语言&#xff0c;那么用Python做数据分析有哪些优势呢?跟着蛋糕往下看。 第一、Python语言自身的优势 Pytho…

ShardingSphere水平、垂直分库、分表和公共表

目录一、ShardingSphere简介二、ShardingSphere-分库分表1、垂直拆分&#xff08;1&#xff09;垂直分库&#xff08;2&#xff09;垂直分表2、水平拆分&#xff08;1&#xff09;水平分库&#xff08;2&#xff09;水平分表三、水平分库操作1、创建数据库和表2、配置分片的规则…

BigGAN

1、BIGGAN 解读1.1、作者 Andrew Brock、Jeff Donahue、Karen Simonyan 1.2、摘要 尽管最近在生成图像建模方面取得了进展&#xff0c;但从 ImageNet 等复杂数据集中 成功生成高分辨率、多样化的样本仍然是一个难以实现的目标。为此&#xff0c;我们以迄 今为止最大的规模训练生…

fastadmin:在新增页面,打开弹窗单选,参数回传

样式&#xff1a;核心代码&#xff1a;一、弹窗的控制器中&#xff1a;// 定义一个公共函数select()&#xff0c;如果这个请求是Ajax&#xff0c;则返回index()函数&#xff0c;否则返回view对象的fetch()函数。 public function select() {if ($this->request->isAjax(…

【软件测试】测试老鸟的迷途,进军高级自动化测试测试......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 很多从业几年的选手…

【阿旭机器学习实战】【37】电影推荐系统---基于矩阵分解

【阿旭机器学习实战】系列文章主要介绍机器学习的各种算法模型及其实战案例&#xff0c;欢迎点赞&#xff0c;关注共同学习交流。 电影推荐系统 目录电影推荐系统1. 问题介绍1.1推荐系统矩阵分解方法介绍1.2 数据集&#xff1a;ml-100k2. 推荐系统实现2.1 定义矩阵分解函数2.2 …

消息中间件的概念

中间件(middleware)是基础软件的一大类&#xff0c;属于可复用的软件范畴。中间件在操作系统软件&#xff0c;网络和数据库之上&#xff0c;应用软件之下&#xff0c;总的作用是为处于自己上层的应用软件提供运行于开发的环境&#xff0c;帮助用户灵活、高效的开发和集成复杂的…

ICA简介:独立成分分析

1. 简介 您是否曾经遇到过这样一种情况&#xff1a;您试图分析一个复杂且高度相关的数据集&#xff0c;却对信息量感到不知所措&#xff1f;这就是独立成分分析 (ICA) 的用武之地。ICA 是数据分析领域的一项强大技术&#xff0c;可让您分离和识别多元数据集中的底层独立来源。 …

PPP简介,PPP分层体系架构,PPP链路建立过程及PPP的帧格式

PPP&#xff08;Point-to-Point Protocol&#xff09;是一种用于在两个网络节点之间传输数据的通信协议。它最初是为在拨号网络上进行拨号连接而开发的&#xff0c;现在已经被广泛应用于各种网络环境中&#xff0c;例如在宽带接入、虚拟专用网&#xff08;VPN&#xff09;等场景…

【JAVA】一个项目如何预先加载数据?

这里写目录标题需求实现AutowiredPostConstruct实例CommandLineRunner实例ApplicationListener实例参考需求 一般我们可能会有一些在应用启动时加载资源的需求&#xff0c;局部或者全局使用&#xff0c;让我们来看看都有哪些方式实现。 实现 Autowired 如果是某个类里需求某…

[1]MyBatis+Spring+SpringMVC+SSM整合

一、MyBatis 1、MyBatis简介 1.1、MyBatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下&#xff0c; iBatis3.x正式更名为MyBatis。代码于2013年11月迁移到Github。…

Vue中如何利用websocket实现实时通讯

首先我们可以先做一个简单的例子来学习一下简单的websocket模拟聊天对话的功能 原理很简单&#xff0c;有点像VUE中的EventBus&#xff0c;用emit和on传来传去 首先我们可以先去自己去用node搭建一个本地服务器 步骤如下 1.新建一个app.js&#xff0c;然后创建pagejson.js文…

【Linux】-- POSIX信号量

目录 POSIX信号量 sem_init - 初始化信号量 sem_destroy - 销毁信号量 sem_wait - 等待信号量&#xff08;P操作&#xff09; 基于环形队列的生产消费模型 数据结构 - 环形结构 实现原理 POSIX信号量 #问&#xff1a;什么是信号量&#xff1f; 1. 共享资源 -> 任何一…

【笔记】两台1200PLC进行S7 通信(1)

使用两台1200系列PLC进行S7通信&#xff08;入门&#xff09; 文章目录 目录 文章目录 前言 一、通信 1.概念 2.PLC通信 1.串口 2.网口 …

时间颗粒度选择(通过选择时间范围和颗粒度展示选项)

<template><div><el-time-selectplaceholder"起始时间"v-model"startTime":picker-options"startPickerOptions"change"changeStartTime"></el-time-select><el-time-selectplaceholder"结束时间&quo…

想招到实干派程序员?你需要这种面试法

技术招聘中最痛的点其实是不精准。技术面试官或CTO们常常会向我们吐槽&#xff1a; “我经常在想&#xff0c;能不能把我们项目中的代码打印出来&#xff0c;作为候选人的面试题的一部分&#xff1f;” “能不能把一个Bug带上环境&#xff0c;让候选人来试试怎么解决&#xf…

mysql中用逗号隔开的字段作查询用(find_in_set的使用)

mysql中用逗号隔开的字段作查询用(find_in_set的使用) 场景说明 在工作中&#xff0c;经常会遇到一对多的关系。想要在mysql中保存这种关系&#xff0c;一般有两种方式&#xff0c;一种是建立一张中间表&#xff0c;这样一条id就会存在多条记录。或者采用第二种方式&#xff…

【数据结构必会基础】关于树,你所必须知道的亿些概念

目录 1.什么是树 1.1浅显的理解树 1.2 数据结构中树的概念 2.树的各种结构概念 2.1 节点的度 2.2 根节点/叶节点/分支节点 2.3 父节点/子节点 2.4祖先节点/子孙节点 2.5兄弟节点 2.6树的度 2.7节点的层次 2.8森林 3. 如何用代码表示一棵树 3.1链式结构 3.1.1 树节…

Gitea Windows环境下服务搭建

前言&#xff1a;这篇文章没有去分析各大平台的优劣势&#xff0c;仅教学大家搭建一个属于自己的git代码管理器&#xff0c;主要作用在局域网内&#xff0c;办公电脑搭建一个简单的Gitea代码管理器。数据库使用SQLite3&#xff0c;环境是windows10。如果不是这个环境的话&#…