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
     */
    @Bean
    public Binding getTopicBinding01(){
        return BindingBuilder
                .bind(getTopicQueue01())
                .to(getTopicExchange())
                //路由键 队列1接收debug级别的消息
                .with("front.#")
                .noargs();
    }

    /**
     * 绑定队列 02
     * @return binding
     */
    @Bean
    public 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 {

    @Resource
    private 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 {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Value("${rabbitmq.simple.queue}")
    private String simpleQueue;

    @Value("${rabbitmq.work.queue}")
    private String workQueue;

    @Override
    public boolean simple(String msg) {
        try {
            rabbitTemplate.convertAndSend(simpleQueue, msg);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean work(String msg) {
        try {
            rabbitTemplate.convertAndSend(workQueue, msg);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean sub(String msg) {
        try {
            //路由模式就不能直接发送消息到队列了, 而是发送到交换机,由交换机进行广播, routingKey为路由Key 订阅模式给""
            rabbitTemplate.convertAndSend("exchange_sub","", msg);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public 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;
        }
    }

    @Override
    public 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字段为消息的级别

 后台接收

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

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

相关文章

ARCGIS PRO3 三维模型OSGB转SLPK场景数据集

1.前言 因项目工作&#xff0c;需要将三维模型发布到arcgisserver上&#xff0c;但arcgisserver只支持slpk格式的模型&#xff0c;于是我开启了漫长的三维模型格式转换之旅&#xff0c;在这里记录下本人踩过的坑。 2.三维模型数据情况 2.1 模型大小&#xff1a;在20GB以上&a…

高级IO|从封装epoll服务器到实现reactor服务器|Part2

项目复习&#xff1a;从封装epoll_server到实现reactor服务器(part2) 项目复习&#xff1a;从封装epoll_server到实现reactor服务器(part2) 基本结构搭建好为什么上面我们写的epoll的recv是不正确的&#xff1f;sock要封装了&#xff0c;要维护缓冲区封装epoll(1)继续先写tcp_…

MATLAB 2024a软件下载安装教程

1-首先下载Matlab&#xff0c;以下迅雷云链接&#xff0c;里面有全版本的matlab&#xff0c;根据自己的需要下载即可&#xff0c;建议下载最新版的&#xff0c;功能会更多&#xff0c;当然内存也会更大。 迅雷云盘迅雷云盘https://pan.xunlei.com/s/VNgH_6VFav8Kas-tRfxAb3XOA…

面试二十三、 strcpy 和memcpy 以及字符串和字符数组相互转换

一、 strcpy 和memcpy 区别 strcpy 和 memcpy 都是浅拷贝操作&#xff0c;它们只是简单地将源数据复制到目标位置&#xff0c;而不会复制源数据所指向的内容。具体来说&#xff1a; strcpy 会复制源字符串的内容直到遇到null终止符&#xff0c;并将其复制到目标字符串中。但是…

中国外运校招测评、在线笔试真题考点、备考攻略|北森测评题库通过技巧

中国外运校招测评、在线笔试真题考点、备考攻略&#xff5c;通过技巧 众所周知&#xff0c;校招主要面向应届高校毕业生&#xff0c;这个群体的突出特点是缺少社会经验&#xff0c;但具备很高的潜质&#xff0c;因此校招通常会关注候选人的综合素质和发展潜质。校招实践中&…

Ubuntu2004 CMake 使用基础

一、环境安装 win10安装wsl ubuntu2004 #windows c盘工程目录建立软链 ln -s /mnt/c /home/vrviu/ 安装cmake、c编译工具 apt install -y cmake g 二、CMakeLists.txt讲解 准备工作 首先&#xff0c;在/home/vrviu 目录建立一个 cmake 目录 以后我们所有的 cmake 练习都会放…

Blender点操作

顶点操作即一般的“布线”操作 1.顶点移动 -先切到顶点模式 -移动&#xff0c;G 或 G X/Y/Z -旋转&#xff0c;R 同上 -缩放&#xff0c;S 同上 2.顶点滑移&#xff0c;用于微调顶点的位置 快捷键&#xff1a;Shift V&#xff0c;G G 3.顶点删除 -选中一个顶点 -按…

项目总结报告(Word原件)+项目总结汇报(PPT)

项目总结报告&#xff08;Word&#xff09;项目总结汇报&#xff08;PPT&#xff09; 1 引言 1.1 编写目的 1.2 背景 1.3 范围 1.4 参考资料 2 项目工作成果 2.1 交付给用户的产品 2.2 交付给研发中心的产品 2.2.1 代码部分 2.2.2 文档部分 2.3 需求完成情况与功能及性能符合性…

微信小程序:5.数据绑定

在Data中定义数据早wxml中进行数据使用 在data中定义数据 在页面对应的js对象中找到data&#xff0c;然后把数据进行定义即可 Page({data: {motto: Hello World,userInfo: {avatarUrl: defaultAvatarUrl,nickName: ,},hasUserInfo: false,canIUseGetUserProfile: wx.canIUse…

牛客NC143 矩阵乘法【中等 矩阵 C++/Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/bf358c3ac73e491585943bac94e309b0 思路 矩阵算法在图像处理、神经网络、模式识别等领域有着广泛的用途。在矩阵乘法中&#xff0c;A矩阵和B矩阵可以做乘法运算必须满足A矩阵的列的数量等于B矩阵的行的数量。运算…

架构师系列- 消息中间件(12)-kafka基础

1、应用场景 1.1 kafka场景 Kafka最初是由LinkedIn公司采用Scala语言开发&#xff0c;基于ZooKeeper&#xff0c;现在已经捐献给了Apache基金会。目前Kafka已经定位为一个分布式流式处理平台&#xff0c;它以 高吞吐、可持久化、可水平扩展、支持流处理等多种特性而被广泛应用…

【docker】安装openjdk

查看可用的 openjdk版本 docker hub 查看地址&#xff1a;https://hub.docker.com/_/openjdk 此图片已被正式弃用&#xff0c;建议所有用户尽快找到并使用合适的替代品。其他官方形象替代品的一些例子&#xff08;按字母顺序列出&#xff0c;没有有意或暗示的偏好&#xff09;…

第三节课,后端登录【1】.2--本人

一、视频链接 网址&#xff1a; 后端用户脱敏和session-CSDN直播 二、代码开始 2.1 新建一个request参数。完成用户登录态键 快捷建&#xff0c; 全局变量 代码&#xff1a; // 3.记录用户的登录态/*** 这段代码是Java Web开发中的一部分&#xff0c;用于在会话&#xff08…

jdk版本冲突,java.lang.UnsupportedClassVersionError: JVMCFRE003

主要是编辑器所用的jdk版本和项目用的不一致导致的&#xff0c;虽然编译通过了&#xff0c;但是运行是会报错 选好后点击Apply点击ok&#xff0c;然后重新编译一遍项目就可以了

qml和c++结合使用

目录 文章简介1. 创建qml工程2. 创建一个类和qml文件&#xff0c;修改main函数3. 函数说明&#xff1a;4. qml 文件间的调用5. 界面布局6. 代码举例 文章简介 初学qml用来记录qml的学习过程&#xff0c;方便后面归纳总结整理。 1. 创建qml工程 如下图&#xff0c;我使用的是…

编译工具各版本与操作系统版本号兼容性冷知识 : JetBrains IntelliJ IDEA 各个主要版本及其对应的操作系统版本号的兼容情况

编译工具各版本与操作系统版本号兼容性冷知识 &#x1f9e0;: JetBrains IntelliJ IDEA 各个主要版本及其对应的操作系统版本号的兼容情况 文章目录 编译工具各版本与操作系统版本号兼容性冷知识 &#x1f9e0;: JetBrains IntelliJ IDEA 各个主要版本及其对应的操作系统版本号…

探索UTONMOS《神念无界-源起山海》元宇宙游戏的奇幻世界

在科技的前沿&#xff0c;元宇宙游戏如同一扇神秘的大门&#xff0c;缓缓开启&#xff0c;引领我们进入一个前所未有的奇幻世界。 UTONMOS《神念无界-源起山海》元宇宙游戏是数字世界的巅峰之作&#xff0c;它打破了现实与虚拟的界限&#xff0c;让玩家能够身临其境地体验各种奇…

二分查找-在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 示例 输入&#xf…

职场不败的社交口才是什么行为

职场不败的社交口才是什么行为 职场不败的社交口才&#xff1a;塑造卓越人际关系的行为艺术 在职场中&#xff0c;社交口才是一项至关重要的能力。它不仅能够帮助我们建立良好的人际关系&#xff0c;更能在关键时刻为我们赢得信任、提升影响力&#xff0c;从而在职场竞争中立于…

HR招聘,怎么做人才测评方案?

一个完整的人才测评环节&#xff0c;离不开对方案的合理设计&#xff0c;更离不开对方案的具体执行。人才测评方案&#xff0c;能够在很大程度上帮助人力资源工作者减轻负担&#xff0c;从繁琐的招聘工作中得到解脱&#xff0c;不再跟陀螺一样转个不停。只有具备合理的人才测评…