RabbitMQ工作模式(5) - 主题模式

 概念

主题模式(Topic Exchange)是 RabbitMQ 中一种灵活且强大的消息传递模式,它允许生产者根据消息的特定属性将消息发送到一个交换机,并且消费者可以根据自己的需求来接收感兴趣的消息。主题交换机根据消息的路由键和绑定队列的路由键进行模糊匹配,支持通配符 *#,从而实现了更灵活的消息路由和分发。

工作流程

  1. 生产者发送消息: 生产者将消息发送到一个主题交换机,并指定一个特定的路由键。

  2. 交换机根据路由键路由消息: 主题交换机根据消息的路由键和绑定队列的路由键进行模糊匹配。路由键可以包含多个单词,以 . 分隔,例如 stock.usd.nyseweather.usa.ca.sunny 等。

  3. 消息发送到匹配的队列: 如果消息的路由键与绑定队列的路由键完全匹配,则将消息发送到对应的队列中。如果路由键中包含通配符 *#,则可以匹配多个单词或多个级别的单词,从而实现更灵活的匹配规则。

  4. 消费者接收消息: 消费者可以根据自己的需求来选择监听匹配的队列,从而接收感兴趣的消息。消费者可以使用通配符 * 匹配一个单词,或使用 # 匹配零个或多个单词。

发送到类型是 topic 交换机的消息的 routing_key 不能随意写,必须满足一定的要求,它必须是一个单词列表,以点号分隔开

优点

  • 灵活性:生产者可以根据消息的特定属性来发送消息,消费者可以根据自己的需求来接收感兴趣的消息。
  • 精确匹配:支持精确的路由键匹配和模糊匹配,可以根据实际需求定义复杂的路由规则。
  • 扩展性:可以根据需要动态地添加和修改绑定规则,而不需要停止消息传递服务。

主题模式适用于需要根据消息的特定属性进行灵活路由和分发的场景,例如事件处理、消息过滤、数据分析等。

 Springboot集成

示例: 系统应用程序测试的时候,会有不同的BUG,测试人员会将不同的BUG按照规范打上标签(相当于routingKey),然后发送到mq中,然后通过主题模式分发;

标签内容:bug归属.模块.等级 例如: back.order.severity

分发规则如下:

第一个消费者是前端的开发人员:处理所有严重的前端BUG:front.#

第二个消费者是后端负责订单模块开发人员:处理所有的后端order模块BUG:back.order.*

另外还有多个消费者处理不同的BUG,这里只用两个做示例

1.创建队列和交换机并绑定

 在TopicConfig中配置

package com.model.config;import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @Author: Haiven* @Time: 2024/4/22 11:55* @Description: TODO*/
@Configuration
public class TopicConfig {/*** 主题模式交换机* @return exchange*/@Bean(name = "topicExchange")public Exchange getTopicExchange(){return ExchangeBuilder.topicExchange("exchange_topic").build();}/*** 主题队列 01* @return queue*/@Bean(name = "topicQueue01")public Queue getTopicQueue01(){return QueueBuilder.durable("queue_topic_01").build();}/*** 主题队列 02* @return queue*/@Bean(name = "topicQueue02")public Queue getTopicQueue02(){return QueueBuilder.durable("queue_topic_02").build();}/*** 绑定队列 01* @return binding*/@Beanpublic Binding getTopicBinding01(){return BindingBuilder.bind(getTopicQueue01()).to(getTopicExchange())//路由键 队列1接收debug级别的消息.with("front.#").noargs();}/*** 绑定队列 02* @return binding*/@Beanpublic Binding getTopicBinding02(){return BindingBuilder.bind(getTopicQueue02()).to(getTopicExchange())// 路由键 队列2接收info级别的消息.with("back.order.*").noargs();}
}

 主题模式的交换机类型为TopicExchange

2.创建消费者

TopicConsumer

package com.model.listener;import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;/*** @Author: Haiven* @Time: 2024/4/22 10:08* @Description: TODO*/
@Component
public class TopicConsumer {@RabbitListener(queues = {"queue_topic_01"})public void topicConsumer01(String msg){System.out.println("消费者 -01- 接收消息:" + msg);}@RabbitListener(queues = {"queue_topic_02"})public void topicConsumer02(String msg){System.out.println("消费者 -02- 接收消息:" + msg);}
}

3.创建生产者并发送消息

package com.model.controller;import com.code.domain.Response;
import com.model.service.RabbitService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** @Author: Haiven* @Time: 2024/4/19 9:46* @Description: TODO*/
@RestController
@RequestMapping("/producer")
public class ProducerController {@Resourceprivate RabbitService rabbitService;@GetMapping("/simple")public Response<Void> simple(String msg){boolean res = rabbitService.simple(msg);return res ? Response.success() : Response.fail();}@GetMapping("/work")public Response<Void> work(String msg){boolean res = rabbitService.work(msg);return res ? Response.success() : Response.fail();}@GetMapping("/sub")public Response<Void> sub(String msg){boolean res = rabbitService.sub(msg);return res ? Response.success() : Response.fail();}@GetMapping("/routing")public Response<Void> routing(String msg, String type){boolean res = rabbitService.routing(msg, type);return res ? Response.success() : Response.fail();}@GetMapping("/topic")public Response<Void> topic(String msg, String type){boolean res = rabbitService.topic(msg, type);return res ? Response.success() : Response.fail();}
}
package com.model.service.impl;import com.model.service.RabbitService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @Author: Haiven* @Time: 2024/4/19 10:51* @Description: TODO*/
@Service
@Slf4j
public class RabbitServiceImpl implements RabbitService {@Resourceprivate RabbitTemplate rabbitTemplate;@Value("${rabbitmq.simple.queue}")private String simpleQueue;@Value("${rabbitmq.work.queue}")private String workQueue;@Overridepublic boolean simple(String msg) {try {rabbitTemplate.convertAndSend(simpleQueue, msg);return true;}catch (Exception e){e.printStackTrace();return false;}}@Overridepublic boolean work(String msg) {try {rabbitTemplate.convertAndSend(workQueue, msg);return true;}catch (Exception e){e.printStackTrace();return false;}}@Overridepublic boolean sub(String msg) {try {//路由模式就不能直接发送消息到队列了, 而是发送到交换机,由交换机进行广播, routingKey为路由Key 订阅模式给""rabbitTemplate.convertAndSend("exchange_sub","", msg);return true;}catch (Exception e){e.printStackTrace();return false;}}@Overridepublic boolean routing(String msg, String type) {System.out.println("理由模式发送消息:msg="+msg+",type="+type+"");try {//路由模式就不能直接发送消息到队列了, 而是发送到交换机,由交换机进行广播, routingKey为路由Key 订阅模式给""rabbitTemplate.convertAndSend("exchange_routing",type, msg);return true;}catch (Exception e){e.printStackTrace();return false;}}@Overridepublic boolean topic(String msg, String type) {System.out.println("主题模式发送消息:msg="+msg+",type="+type+"");try {//主题模式会根据 type的通配符进行分发rabbitTemplate.convertAndSend("exchange_topic",type, msg);return true;}catch (Exception e){e.printStackTrace();return false;}}
}

4.发送消息

接口调用发送消息, type字段为消息的级别

 后台接收

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

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

相关文章

RabbitMQ的理论知识点,和使用RabbitMQ时常见的问题点【理论】!

不管使用任何语言调用RabbitMQ 一般都会存在各种问题&#xff0c;我整理了一下 我觉得会遇到的常见问题&#xff0c;并记录了 解决思路 。没有提供具体代码&#xff0c;后续有时间写个代码体会一下&#xff0c;实际有了解决思路&#xff0c;百度里有很多代码让我们使用。哈哈 …

盲人地图使用的革新体验:助力视障人士独立、安全出行

在我们日常生活中&#xff0c;地图导航已经成为不可或缺的出行工具。而对于盲人群体来说&#xff0c;盲人地图使用这一课题的重要性不言而喻&#xff0c;它不仅关乎他们的出行便利性&#xff0c;更是他们追求生活独立与品质的重要一环。 近年来&#xff0c;一款名为蝙蝠…

代码随想录算法训练营第三十八天| 动态规划,509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯

目录 动态规划 题目链接&#xff1a; 509. 斐波那契数 思路 代码 题目链接&#xff1a; 70. 爬楼梯 思路 代码 题目链接&#xff1a; 746. 使用最小花费爬楼梯 思路 代码 总结 动态规划 Dynamic programming&#xff0c;DP问题。某一问题包含很多重叠的子问题&#x…

echarts地图叠加百度地图底板实现数据可视化

这里写自定义目录标题 echarts地图叠加百度地图实现数据可视化echarts地图叠加百度地图实现数据可视化 实现数据可视化时,个别情况下需要在地图上实现数据的可视化,echarts加载geojson数据可以实现以地图形式展示数据,例如分层设色或者鼠标hover展示指标值,但如果要将echa…

React 之 组件模块依赖

导入&#xff08;Import&#xff09;和导出&#xff08;exporing&#xff09;组件 在一个文件中声明多个组件&#xff0c;但是文件变得太大的话就不方便查看了。要解决此问题&#xff0c;你可以将一个组件放到一个单独的文件中并&#xff08;导出&#xff09; export 组件&…

运筹系列91:vrp算法包PyVRP

1. 介绍 PyVRP使用HGS&#xff08;hybrid genetic search&#xff09;算法求解VRP类问题。在benchmark上的评测结果如下&#xff0c;看起来还不错&#xff1a; 2. 使用例子 2.1 CVRP COORDS [(456, 320), # location 0 - the depot(228, 0), # location 1(912, 0), …

C++进阶之路——关键字

C进阶——关键字 本系列博客主要对于已经有一定C/C基础的网友&#xff0c;欢迎志同道合的朋友来进行纯粹的技术交流&#xff01;&#xff01;&#xff01; 一、const 在C中&#xff0c;const 关键字是一个非常重要的特性&#xff0c;用于定义变量或对象的值为常量&#xff0c;…

通往AGI路上,DPU将如何构建生成式AI时代的坚实算力基石?

4月19日&#xff0c;在以“重构世界 奔赴未来”为主题的2024中国生成式AI大会上&#xff0c;中科驭数作为DPU新型算力基础设施代表&#xff0c;受邀出席了中国智算中心创新论坛&#xff0c;发表了题为《以网络为中心的AI算力底座构建之路》主题演讲&#xff0c;勾勒出在通往AGI…

Xcode 15构建问题

构建时出现的异常&#xff1a; 解决方式&#xff1a; 将ENABLE_USER_SCRIPT_SANDBOXING设为“no”即可&#xff01;

GateWay具体的使用!!!

一、全局Token过滤器 在Spring Cloud Gateway中&#xff0c;实现全局过滤器的目的是对所有进入系统的请求或响应进行统一处理&#xff0c;比如添加日志、鉴权等。下面是如何创建一个全局过滤器的基本步骤&#xff1a; 步骤1: 创建过滤器类 首先&#xff0c;你需要创建一个实现…

表---商场 nine

CREATE TABLE gao25 (id int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,shopId int(11) NOT NULL COMMENT 店铺ID,goodsId int(11) NOT NULL COMMENT 商品ID,attrId int(11) NOT NULL COMMENT 属性名称,attrVal text NOT NULL COMMENT 属性值,createTime datetime NOT NULL …

实验 1--SQL Server2008数据库开发环境

文章目录 实验 1--SQL Server2008数据库开发环境2.4.1 实验目的2.4.2 实验准备2.4.3 实验内容1.利用 SSMS 访问系统自带的Report Server 数据库。2.熟悉了解 SMSS对象资源管理器树形菜单相关选择项的功能。(1)右键单击数据库Report Server&#xff0c;查看并使用相关功能;(2)选…

scp用法

scp常用参数&#xff1a; 命令选项 含义 -1 使用ssh协议版本1 -2 使用ssh协议版本2 -4 使用ipv4 6 使用ipv6 -B 以批处理模式运行 -C 使用压缩 -F 指定ssh配置文件 -l 指定带宽限制 -o 指定使用的ssh选项 -P 指定远程主机的端口号 -p 保留…

[C++基础学习]----02-C++运算符详解

前言 C中的运算符用于执行各种数学或逻辑运算。下面是一些常见的C运算符及其详细说明&#xff1a;下面详细解释一些常见的C运算符类型&#xff0c;包括其原理和使用方法。 正文 01-运算符简介 算术运算符&#xff1a; a、加法运算符&#xff08;&#xff09;&#xff1a;对两个…

基于openwrt交叉编译opencv4.9.0版本

源码包的获取 源码获取有两种方式&#xff0c;一种是通过编译时在makefile指定它的git地址&#xff0c;在编译时下载&#xff0c;这种很依赖网速&#xff0c;网速不好时&#xff0c;编译会失败。另一种是我们将源码的压缩包下载到本地&#xff0c;放到我们的SDK中&#xff0c;…

以场景驱动CMDB数据治理经验分享

数据治理是 CMDB 项目实施中难度最大、成本最高的环节&#xff0c;是一个长期治理的过程&#xff0c;而行业很少提出 CMDB 数据治理的技术实现方案。CMDB 数据治理不仅需要解决配置管理工程性的技术问题&#xff0c;还要基于运维组织的特点&#xff0c;建立适应性的配置运营能力…

DS进阶:并查集

一、并查集的原理 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这…

SCSS全局配置 vue项目(二)

目录 1、先要查看node版本 2、安装对应的node-sass、sass-loader版本 2.1根据项目使用的node版本安装对应的node-sass版本 2.2根据node-sass版本选择兼容的sass-loader版本&#xff0c;不然项目无法正常运行 3、在 vue.config.js 中配置&#xff1a; 4、在组件中…

深入浅出掌握CSS选择器

CSS选择器是CSS规则的核心组成部分&#xff0c;它们犹如一把钥匙&#xff0c;帮助开发者精准锁定并装饰HTML文档中的各类元素。正确理解和熟练运用CSS选择器&#xff0c;能够极大提升代码效率和页面表现力。本文将系统全面地剖析CSS选择器的种类、用途及应用场景&#xff0c;并…

国家级会议报道:贝锐蒲公英异地组网高效实现前方数据回传

作为市委宣传部的国有新闻媒体&#xff0c;在日常工作中会派遣大量人员外出进行采访、报道&#xff0c;还经常面临国家级重要会议或活动的报道任务。 在这些工作中&#xff0c;前方人员往往需要和后方人员协同、保证内容的时效性&#xff0c;及时反馈现场的相关资料和信息、访…