SpringBoot3整合RabbitMQ之四_发布订阅模型中的fanout模型

news2024/10/6 10:19:46

SpringBoot3整合RabbitMQ之四_发布订阅模型中的fanout模型

文章目录

  • SpringBoot3整合RabbitMQ之四_发布订阅模型中的fanout模型
  • 3. 发布/订阅模型之fanout模型
    • 1. 说明
    • 1. 消息发布者
      • 1. 创建工作队列的配置类
      • 2. 发布消费Controller
    • 2. 消息消费者One
    • 3. 消息消费者Two
    • 4. 消息消费者Three
    • 5. 输出结果

3. 发布/订阅模型之fanout模型

在这里插入图片描述

1. 说明

RabbitMQ广播(Fnaout)模型,也称为发布/订阅模型,是一种消息传递模式,用于将消息发送给多个消费者。在广播模型中,生产者发送消息到一个交换机(Exchange),而交换机将消息广播给所有绑定到它上面的队列(Queue),每个队列都有一个消费者监听并处理消息。

下面是 RabbitMQ 广播模型的基本原理和步骤:

  1. 交换机(Exchange): 生产者将消息发送到交换机。交换机负责将消息路由到一个或多个与之绑定的队列。
  2. 队列(Queue): 每个消费者都有一个独立的队列。队列存储交换机发送的消息,并将其提供给消费者。
  3. 绑定(Binding): 将队列与交换机进行绑定,指定一个或多个交换机将消息发送到该队列。
  4. 消费者(Consumer): 消费者监听队列,并处理收到的消息。

在广播模型中,有两种类型的交换机可供选择:

  • Fanout Exchange(扇出交换机): 扇出交换机会将消息广播到绑定到它上面的所有队列,无视消息的路由键(Routing Key)。
  • Headers Exchange(头交换机): 头交换机根据消息的 header 信息来进行匹配,并将消息发送到与 header 匹配的队列。

下面是使用 RabbitMQ 广播模型的基本步骤:

  1. 创建交换机,指定交换机类型为 Fanout Exchange。
  2. 创建队列,并将其绑定到交换机上。
  3. 生产者发送消息到交换机。
  4. 消费者监听队列,接收并处理消息。

使用 RabbitMQ 广播模型可以实现消息的一对多传递,适用于需要向多个消费者发送相同消息的场景,比如日志系统、通知系统等。

1. 消息发布者

1. 创建工作队列的配置类

package com.happy.msg.config;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * <p>
 *
 * @Description: 工作队列模型_创建名称为 work_queue 的队列 <br>
 * </p>
 * @Datetime: 2024/3/27 18:18
 * @Author: Yuan · JinSheng <br>
 * @Since 2024/3/27 18:18
 */
@Configuration
public class WorkQueueConfig {
    @Bean
    Queue workQueue() {
        return QueueBuilder.durable("work_queue").build();
    }
}

2. 发布消费Controller

package com.happy.msg.publisher;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * @Description: 生产消息的控制器 <br>
 * </p>
 * @Datetime: 2024/3/27 10:53
 * @Author: Yuan · JinSheng <br>
 * @Since 2024/3/27 10:53
 */
@RestController
@RequestMapping("/work")
public class WorkQueuePublisherController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/send")
    public String sentMessage() {
        for (int i = 1; i <=10 ; i++) {
            rabbitTemplate.convertAndSend("work_queue", "work_queue队列第["+i+"]条消息,hello,rabbitmq"+i);
        }
        return "发送成功";
    }
}

2. 消息消费者One

package com.happy.msg.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
/**
 * <p>
 * @Description: 工作队列模型_消息消费者一 <br>
 * </p>
 * @Datetime: 2024/3/28 20:28
 * @Author: Yuan · JinSheng <br>
 * @Since 2024/3/28 20:28
 */
@Slf4j
@Component
public class WorkQueueConsumerOne {

    /***
     * @param message 消息
     * @Description: 监听work_queue队列中的消息,当客户端启动后,work_queue队列中的所有的消息都被此消费者消费并打印
     * @Author: Yuan · JinSheng
     */

    @RabbitListener(queues = "work_queue")
    public void msg(Message message){
        byte[] messageBody = message.getBody();
        String msg = new String(messageBody);
        log.info("WorkQueueConsumerOne接收到work_queue队列中的消息==={},===接收时间==={}",msg, LocalDateTime.now());
    }
}

  1. 输出结果
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[1]条消息,hello,rabbitmq1,===接收时间===2024-03-29T10:34:34.468074100
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[3]条消息,hello,rabbitmq3,===接收时间===2024-03-29T10:34:34.469081600
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[5]条消息,hello,rabbitmq5,===接收时间===2024-03-29T10:34:34.469976
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[7]条消息,hello,rabbitmq7,===接收时间===2024-03-29T10:34:34.469976
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[9]条消息,hello,rabbitmq9,===接收时间===2024-03-29T10:34:34.470811800

3. 消息消费者Two

package com.happy.msg.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
/**
 * <p>
 * @Description: 工作队列模型_消息消费者二<br>
 * </p>
 * @Datetime: 2024/3/28 20:30
 * @Author: Yuan · JinSheng <br>
 * @Since 2024/3/28 20:30
 */
@Slf4j
@Component
public class WorkQueueConsumerTwo {

    /***
     * @param message 消息
     * @Description: 监听work_queue队列中的消息,当客户端启动后,work_queue队列中的所有的消息都被此消费者消费并打印
     * @Author: Yuan · JinSheng
     */

    @RabbitListener(queues = "work_queue")
    public void msg(Message message){
        byte[] messageBody = message.getBody();
        String msg = new String(messageBody);
        log.info("WorkQueueConsumerTwo接收到work_queue队列中的消息==={},===接收时间==={}",msg, LocalDateTime.now());
    }
}

4. 消息消费者Three

package com.happy.msg.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
/**
 * <p>
 * @Description: 工作队列模型_消息消费者三<br>
 * </p>
 * @Datetime: 2024/3/28 20:30
 * @Author: Yuan · JinSheng <br>
 * @Since 2024/3/28 20:30
 */
@Slf4j
@Component
public class WorkQueueConsumerTwo {

    /***
     * @param message 消息
     * @Description: 监听work_queue队列中的消息,当客户端启动后,work_queue队列中的所有的消息都被此消费者消费并打印
     * @Author: Yuan · JinSheng
     */

    @RabbitListener(queues = "work_queue")
    public void msg(Message message){
        byte[] messageBody = message.getBody();
        String msg = new String(messageBody);
        //log.info("WorkQueueConsumerTwo接收到work_queue队列中的消息==={},===接收时间==={}",msg, LocalDateTime.now());
        System.out.println("WorkQueueConsumerTwo接收到work_queue队列中的消息==="+msg+",===接收时间==="+LocalDateTime.now());
    }
}

5. 输出结果

可看到消息被三个消费者按相等数量消费,总共10条消息,消费者1消费了4条,其他两个消费者消费了3条消息

WorkQueueConsumerTwo接收到work_queue队列中的消息===work_queue队列第[3]条消息,hello,rabbitmq3,===接收时间===2024-03-29T10:39:32.942546200
WorkQueueConsumerThree接收到work_queue队列中的消息===work_queue队列第[2]条消息,hello,rabbitmq2,===接收时间===2024-03-29T10:39:32.942546200
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[1]条消息,hello,rabbitmq1,===接收时间===2024-03-29T10:39:32.942037700
WorkQueueConsumerTwo接收到work_queue队列中的消息===work_queue队列第[6]条消息,hello,rabbitmq6,===接收时间===2024-03-29T10:39:32.943806300
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[4]条消息,hello,rabbitmq4,===接收时间===2024-03-29T10:39:32.944336900
WorkQueueConsumerTwo接收到work_queue队列中的消息===work_queue队列第[9]条消息,hello,rabbitmq9,===接收时间===2024-03-29T10:39:32.944336900
WorkQueueConsumerThree接收到work_queue队列中的消息===work_queue队列第[5]条消息,hello,rabbitmq5,===接收时间===2024-03-29T10:39:32.944336900
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[7]条消息,hello,rabbitmq7,===接收时间===2024-03-29T10:39:32.944336900
WorkQueueConsumerOne接收到work_queue队列中的消息===work_queue队列第[10]条消息,hello,rabbitmq10,===接收时间===2024-03-29T10:39:32.944336900
WorkQueueConsumerThree接收到work_queue队列中的消息===work_queue队列第[8]条消息,hello,rabbitmq8,===接收时间===2024-03-29T10:39:32.944336900

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

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

相关文章

windows上使用influx2.7学习

参考 官方文档&#xff1a;https://docs.influxdata.com/influxdb/v2/ 下载 需要下载两样东西&#xff1a;influxd.exe和influx.exe influxd:influx数据库的服务端。下载地址&#xff1a;https://dl.influxdata.com/influxdb/releases/influxdb2-2.7.5-windows.zipinflux:连…

C# 实现子进程跟随主进程关闭

文章目录 前言一、如何实现&#xff1f;1、创建作业对象&#xff08;1&#xff09;、创建对象&#xff08;2&#xff09;、设置销毁作业时&#xff0c;关闭拥有的进程 2、子进程加入作业对象3、销毁作业对象&#xff08;1&#xff09;、手动销毁&#xff08;2&#xff09;、所在…

算法设计与分析实验报告c++实现(连续邮资问题、卫兵布置问题、圆排列问题、求解填字游戏问题、分支限界法求解旅行售货员(TSP)问题)

一、 实验目的 1&#xff0e;加深学生对算法设计方法的基本思想、基本步骤、基本方法的理解与掌握&#xff1b; 2&#xff0e;提高学生利用课堂所学知识解决实际问题的能力&#xff1b; 3&#xff0e;提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 1.连续邮资…

最好用的安卓按钮(3)

属性解释 按钮文字 app:text“床前明月光” 按钮文字颜色 app:textColor“color/color_white” 按钮文字大小 app:textSize“22sp” 按钮背景颜色 app:color_normal“color/color_accent” 0x2 单独设置每个圆角 效果 代码 <top.androidman.SuperButton android:layo…

软考 系统架构设计师系列知识点之数据库基本概念(4)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之数据库基本概念&#xff08;3&#xff09; 所属章节&#xff1a; 第6章. 数据库设计基础知识 第1节 数据库基本概念 6.1.3 数据库管理系统 DBMS&#xff08;DataBase Management System&#xff0c;数据库管理系统&am…

【Linux】SSH协议应用

SSH协议 SSH简介实现OpenSSH ssh中的四个文件~/.ssh文件路径实验解析 SSH 简介 SSH&#xff08;secure shell&#xff09;只是一种协议&#xff0c;存在多种实现&#xff0c;既有商业实现&#xff0c;也有开源实现。本文针对的实现是OpenSSH&#xff0c;它是自由软件&#xf…

ZYNQ实验--CIC插值滤波器实验

一、CIC滤波器介绍 CIC (Cascaded Integrator-Comb) 滤波器是一种常用的数字信号处理滤波器&#xff0c;主要用于降采样&#xff08;decimation&#xff09;和升采样&#xff08;interpolation&#xff09;操作。它具有简单的硬件实现、高效的运算速度以及适用于需要快速处理的…

应届生选导师的创业公司,还是去中厂?

点击上方&#xff0c;选择“置顶/星标公众号” 福利干货&#xff0c;第一时间送达 导师是做自动化设备的控制软件&#xff0c;公司做纯软件。导师能给一样的工资&#xff0c;五人左右团队&#xff0c;潜在收入可能要高一些。纠结哪个对今后的发展更好一些。 大家好&#xff0…

【论文阅读笔记】Mamba模型代码理解

0.开源代码地址 官方实现&#xff1a;state-spaces/mamba (github.com) 最简化实现&#xff1a;johnma2006/mamba-minimal: Simple, minimal implementation of the Mamba SSM in one file of PyTorch. (github.com) 直接实现&#xff1a;alxndrTL/mamba.py: A simple and e…

Java 接口提示500,但console并不报错。

因为习惯了C语言printf打印&#xff0c;且当时并不明白try catch意义所在 如图所示&#xff0c;下添加了行号打印 但只打印出了line 89&#xff0c;无line 91&#xff0c;也无报错 所以使用try catch 包裹Sql查询封装函数 e.printStackTrace(); 果真打印出了 查看Entity类&…

【经典算法】LeetCode25:K 个一组翻转链表(Java/C/Python3,Hard)

#算法 目录 题目描述思路及实现方式一&#xff1a;递归思路代码实现Java 版本C 语言版本Python3 版本 复杂度分析 方式二&#xff1a;迭代和原地反转思路代码实现Java 版本C 语言版本Python3 版本 复杂度分析 总结相似题目 标签&#xff1a;链表、递归 题目描述 给你链表的头…

DFS:floodfill算法解决矩阵联通块问题

floodfill&#xff0c;翻译为洪水灌溉&#xff0c;而floodfill算法本质上是为了解决在矩阵中性质相同的联通块问题。 一、图像渲染 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int dx[4]{0,0,1,-1};int dy[4]{1,-1,0,0};int prev;//记住初始值int m,…

什么是广播系统语言传输指数 STIPA

基础知识 通过广播系统播放一个确定的信号&#xff08;STIPA 测试信号&#xff09;&#xff0c;再在待测点测量其到达后的质量即可。IEC 60268-16 标准中定义通过单一值表示清晰度结果&#xff0c;0 表示完全无法理解&#xff0c;1 表示完美理解。测量单位是 STI&#xff08;语…

C#探索之路基础夯实篇(3):面向对象的三大特性和五大原则详解

文章目录 前提&#xff1a;一、特性&#xff1a;二、原则&#xff1a;三、示例1. 单一职责原则 (Single Responsibility Principle, SRP)&#xff1a;2. 开放-封闭原则 (Open-Closed Principle, OCP)&#xff1a;3. 里氏替换原则 (Liskov Substitution Principle, LSP)&#xf…

移动硬盘能当u盘重装系统吗?做启动数据还能恢复吗

在数字时代&#xff0c;随着技术的不断发展&#xff0c;我们越来越依赖于各种存储设备&#xff0c;其中移动硬盘以其大容量和便携性受到广大用户的青睐。不过&#xff0c;有时我们可能会遇到需要使用U盘来重装系统的情况&#xff0c;而手头又没有合适的U盘。这时&#xff0c;我…

Spring Boot-01-通过一个项目快速入门

官方参考文档&#xff1a;Spring Boot Reference Documentation 0. 概述 Spring的缺点&#xff1a; 1. 配置繁琐&#xff1a;虽然Spring的组件代码是轻量级&#xff0c;但它的配置却是重量级的。 2. 依赖繁琐&#xff1a;项目的依赖管理也是一件耗时耗力的事情。分析要导入哪…

03-JAVA设计模式-工厂模式详解

工厂模式 工厂设计模式是一种创建型设计模式&#xff0c;它提供了一种封装对象创建过程的机制&#xff0c;将对象的创建与使用分离。 这种设计模式允许我们在不修改客户端代码的情况下引入新的对象类型。 在Java中&#xff0c;工厂设计模式主要有三种形式&#xff1a;简单工厂…

【CNN】ConvMixer探究ViT的Patch Embedding: Patches Are All You Need?

Patches Are All You Need? 探究Patch Embedding在ViT上的作用&#xff0c;CNN是否可用该操作提升性能&#xff1f; 论文链接&#xff1a;https://openreview.net/pdf?idTVHS5Y4dNvM 代码链接&#xff1a;https://github.com/tmp-iclr/convmixer 1、摘要 ViT的性能是由于T…

基于Spark中随机森林模型的天气预测系统

基于Spark中随机森林模型的天气预测系统 在这篇文章中&#xff0c;我们将探讨如何使用Apache Spark和随机森林算法来构建一个天气预测系统。该系统将利用历史天气数据&#xff0c;通过机器学习模型预测未来的天气情况&#xff0c;特别是针对是否下雨的二元分类问题。 简介 Ap…

【unity】【C#】延时调用(协程)和场景管理

文章目录 什么是协程协程的应用 - IEnumerator如何控制协程的暂停协程的另一种写法 - Invoke场景管理 多看代码块中的注释 什么是协程 A coroutine alows vou to spreacwhere it left off on the following anc return control toolinencoeframe. 协程允许您将任务分布在多个帧…