一点点地给你分析RabbiMQ的几种消息模型

商城-RabbitMQ及消息同步-五种消息模型 商城-RabbitMQ及消息同步-五种消息模型2.五种消息模型2.1.基本消息模型2.1.1.生产者发送消息2.1.2.管理工具中查看消息2.1.3.消费者获取消息2.1.4.消息确认机制(ACK)2.1.4.1.自动ACK存在的问题2.1.4.2.演示手动ACK2.2.work消息模型2.2.1.生产者2.2.2.消费者12.2.3.消费者22.2.4.能者多劳2.3.订阅模型分类2.4.订阅模... 阅读详情

1.RabbitMQ的交换机

Direct Exchange(直连交换机), Fanout Exchange(扇型交换机), Topic Exchange(主题交换机)与 Headers Exchange(头交换机),RabbitMQ的交换机是这四种,而他们也是各有特点,我们这个不能看其他的文章,首先就得从RabbitMQ的官网上去看这块的内容,毕竟,官网才是正道。

为什么会有交换机,不是直接有队列呢?官网给了我们一个最经典的解释:

The core idea in the messaging model in RabbitMQ is that the producer never sends any messages directly to a queue. Actually, quite often the producer doesn't even know if a message will be delivered to any queue at all.

意思就是:RabbitMQ中消息传递模型的核心思想是生产者从不将任何消息直接发送到队列。实际上,生产者通常甚至不知道消息是否会被传递到任何队列。

也就是说,RabbitMQ在传递消息的时候,是先从生产者发送给交换机,然后这个时候,由交换机发送给队列,我们在生产消息的时候,实际上如果不关注交换机和队列的绑定的话,我们都不知道消息是发送到哪一个队列。

1.Direct Exchange(直连交换机)

直连型交换机其实是属于最简单的一种交换模式,在这里队列使用路由密钥K绑定到交换机,当具有路由键R的新消息到达直接交换时,如果K=R,则交换会将其路由到队列。

直连型交换机通常用于以轮循方式在多个工作程序(同一应用程序的实例)之间分配任务。

以上都是官网上给我们的解释,大家可以翻译一下他的英文注释即可。

2.Fanout Exchange(扇型交换机)

扇形交换机将消息路由到与其绑定的所有队列,并且路由键将被忽略。如果将N个队列绑定到扇出交换机,则将新消息发布到该交换机时,该消息的副本将传递到所有N个队列。

大家划重点,文档中是不是说明了路由键将被忽略,也就是说路由键在扇形交换机里没有作用,故消息队列绑定扇形交换机时,路由键可为空。而他实际上就相当于一个广播的性质。

3.Topic Exchange(主题交换机)

主题交换机实际上就是一个发布/订阅,根据消息路由键和用于将队列绑定到交换机的模式之间的匹配将消息路由到一个或多个队列。主题交换类型通常用于实现各种发布/订阅模式变体。主题交换通常用于消息的多播路由。

主体交换机官方案例没有图,但是我们可以画一个图来理解一下

图中,如果你要绑定的时候使用了通配符了,那么你再给交换机传递消息的时候,注意,RoutingKey开头是你绑定的时候设置的通配符才可以,符号“#”匹配一个或多个词。

4.Headers Exchange(头交换机)

头交换机不处理路由键。而是根据发送的消息内容中的headers属性进行匹配。在绑定Queue与Exchange时指定一组键值对;当消息发送到RabbitMQ时会取到该消息的headers与Exchange绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。

既然我们已经说明了这么多的交换机,那么就应该给大家写一个配置,然后让大家更快地能够实际运用到项目中。

2.DemoConfig

Direct类型绑定

    //这里先定义Queue和交换机以及RoutingKey

    /**
     * 消息的routing key与队列的binding key相同的队列
     */
    public static final String DIRECT_QUEUE_NAME = "Direct_Queue";
    /**
     * direct 交换机
     */
    public static final String DIRECT_EXCHANGE_NAME = "Direct_Exchange";
    /**
     * routing key
     */
    public static final String DIRECT_ROUTING_KEY_NAME = "Direct_Routing_Key";
    
    //创建队列+队列交换机绑定
    /**
     * Direct交换机
     * @return
     */
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange(DIRECT_EXCHANGE_NAME);
    }
    /**
     * 创建一条持久化的、非排他的、非自动删除的队列
     * @return
     */
    @Bean
    public Queue directQueue(){
        return new Queue(DIRECT_QUEUE_NAME);
    }

    /**
     * Binding,将该routing key的消息通过交换机转发到该队列 匹配键:DIRECT_ROUTING_KEY_NAME
     * @return
     */
    @Bean
    public Binding directBinding(){
        return BindingBuilder.bind(directQueue()).to(directExchange()).with(DIRECT_ROUTING_KEY_NAME);
    }

Fanout类型绑定

    /**
     * 与fanout绑定的第一个队列
     */
    public static final String FIRST_FANOUT_QUEUE_NAME = "First_Fanout_Queue";
    
    /**
     * 与fanout交换机绑定的第二个队列
     */
    public static final String SECOND_FANOUT_QUEUE_NAME = "Send_Fanout_Queue";
    
    /**
     * fanout 交换机
     */
    public static final String FANOUT_EXCHANGE_NAME = "Fanout_Exchange";


     @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(FANOUT_EXCHANGE_NAME);
    }

    @Bean
    public Queue firstFanoutQueue() {
        return new Queue(FIRST_FANOUT_QUEUE_NAME);
    }

    @Bean
    public Queue secondFanoutQueue() {
        return new Queue(SECOND_FANOUT_QUEUE_NAME);
    }

    @Bean
    public Binding firstFanoutBinding() {
        return BindingBuilder.bind(firstFanoutQueue()).to(fanoutExchange());
    }

    @Bean
    public Binding secondFanoutBinding() {
        return BindingBuilder.bind(secondFanoutQueue()).to(fanoutExchange());
    }

Header类型绑定

    /**
     * 处理对象的MQ队列
     */
    public static final String HANDLER_OBJECT_QUEUE_NAME = "Handler_Object_Queue";

    /**
     * 处理对象的MQ队列
     */
    public static final String HANDLER_OBJECT_EXCHANGE = "Handler_Object_Exchange";
    
    @Bean
    public Queue handleObjectQueue() {
        return new Queue(HANDLER_OBJECT_QUEUE_NAME);
    }

    @Bean
    public HeadersExchange headersExchange(){
        return new HeadersExchange(HANDLER_OBJECT_EXCHANGE);
    }
    @Bean

    public Binding headerBinding(){
        Map<String, Object> map = new HashMap<>();
        map.put("header1", "value1");
        map.put("header2", "value2");
        return BindingBuilder.bind(handleObjectQueue()).to(headersExchange()).whereAll(map).match();
    }

Topic类型绑定

 /**
     * 与topic绑定的第一个队列
     *
     */
    public final static String FIRST_TOPIC_QUEUE = "First_Topic_Queue";
    /**
     * 与topic绑定的第二个队列
     *
     */
    public final static String SECOND_TOPIC_QUEUE = "Second_Topic_Queue";
    /**
     * 与topic绑定的第二个队列
     *
     */
    public final static String TOPIC_EXANGE_NAME = "Topic_Exchange";
    
    /**
     *  Topic型交换机模型:将routingKey与binding key做通配符匹配,转发消息到匹配的队列
     *  “#”匹配一个词或多个词,“*”只匹配一个词。
     */
    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(TOPIC_EXANGE_NAME);
    }
    @Bean
    public Queue firstTopicQueue() { return new Queue(FIRST_TOPIC_QUEUE);}

    @Bean
    public Queue secondTopicQueue() {
        return new Queue(SECOND_TOPIC_QUEUE);
    }

    /**
     * 将FirstQueue和TopicExchange绑定,绑定的键为FIRST_TOPIC_QUEUE
     */
    @Bean
    public Binding firstTopicBinding() {
        return BindingBuilder.bind(firstTopicQueue()).to(topicExchange()).with(FIRST_TOPIC_QUEUE);
    }
    /**
     * 将SecondQueue和TopicExchange绑定,绑定的键为通配符使用的 Topic_#
     * 消息携带的路由键是以Topic.开头,都会分发到该队列
     */
    @Bean
    public Binding secondTopicBinding() {
        return BindingBuilder.bind(secondTopicQueue()).to(topicExchange()).with("Topic.#");
    }

至于发送消息,相信大家肯定也都会,

 rabbitTemplate.convertAndSend(RabbitMQConfig.TOPIC_EXANGE_NAME, routingKey, message,new CorrelationData(UUID.randomUUID().toString()));

第一个参数:交换机配置

第二个参数:RoutingKey

第三个参数:消息

第四个参数:对于使用消息确认的时候,需要的一个唯一ID。

发送成功之后,我们同样需要看是否发送成功,这时候就有了confirm,而这个confirm,就是用来确认消息是否发送成功,而这块也是从你在配置RabbitMQ的时候配置决定的,是否手动确认消息发送成功。

    #是否支持发布确认
    publisher-confirms: true
    #是否支持发布返回
    publisher-returns: true

相对应的,你就应该在消息发出的时候加入一些代码,比如:

        //ACK确认机制
        rabbitTemplate.setConfirmCallback(confirmCallback);
        rabbitTemplate.convertAndSend(RabbitMQConfig.SIMPLE_QUEUE_NAME, message);

而ConfirmCallback里面的参数呢,是从下面来的。

confirm确认 此处的confirm确认是发送的ACK确认机制
    RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            if(ack){
                System.out.println(correlationData);
                //如果confirm返回成功 则进行更新
                System.out.println("confirm确认消息已经发出");
            } else {
                //失败则进行具体的后续操作:重试 或者补偿等手段
                System.err.println("异常处理...");
            }
        }
    };

以上的代码可以直接和上一篇阿粉讲的RabbitMQ整合Springboot的案例直接放入就可以使用。

MQ-常见消息模型及基本消息队列(basicQueue) 建立connection创建channel利用channel声明队列利用channel向队列发送消息建立connection创建channel利用channel声明队列定义consumer的消费行为handleDelivery()利用channel将消费者与队列绑定。 阅读详情

相关推荐

基于TDOA的chan算法(定位算法)

Chan算法原理 TDOA(TDOA,the time differences of arrival,到达时间差),Chan算法是TDOA定位方法的一个很好用的方法。 Chan算法是非递归双曲线方程组解法,具有解析表达式解,主要特点是:在测量误差服从理想高斯分布时,它的定位精度高、计算量小,并且可以通过增加已确定点的数量来提高算法精度。 该算法的推导前提是基于测量误差为零均值高斯随机变量,对于实际环境中误差较大的测量值,比如在有非视距误差的环境下,该算法的性能会有显著下降。二维情况下,可分为只有三个点参与定

优快云不再更新 2万+

消息队列系列5 - RabbitMQ安装与测试 (荣耀典藏版)

RabbitMQ安装与测试教学

人生若只初相见@的博客 1万+

ArcGIS Pro中如何批量替换数据源

不知您是否遇到过下面情况:ArcGIS Pro的Map/Scene中所引用的数据源被移动或重命名了,导致Map/Scene中找不到之前的数据,出现红色叹号;已有一个Map模板文件,图层的样式符号都是设置好的,想批量设置成另外一个数据源,复用该模板文件中的样式符号。 如果您在ArcGIS Pro的使用过程中遇到了上面情况,那么可以参考本篇文章,本文以图层存储在同一GDB中为例介绍。 情况一:Map中已有图层的数据源被移动了 原始Map长这样: 当数据源位置改变之后,显示找不到数据源的红色叹号: 这时如果右

xinying180的博客 7948

RabbitMq配置参数详解

# base spring.rabbitmq.host: 服务Host spring.rabbitmq.port: 服务端口 spring.rabbitmq.username: 登陆用户名 spring.rabbitmq.password: 登陆密码 spring.rabbitmq.virtual-host: 连接到rabbitMQ的vhost spring.rabbitmq.addresses: 指定client连接到的server的地址,多个以逗号分隔(优先取addresses,然后再取host) sp

hu_zhiwei3的博客 2653

AMP架构下的核间通信:RPMSG与共享内存原理详解

本文以RK3568等异构多核硬件为例,深入浅出解析了AMP架构下核间通信的核心逻辑,阐明RPMSG并非替代共享内存,而是以共享内存为数据载体、硬件信箱为中断通知工具、VirtIO为数据管理规则,构建的标准化高层协议与框架,为开发者提供简洁API,实现不同操作系统核心间高效通信。

qq_61335271的博客 2049

泛微OA表单开发实战:如何用JavaScript动态控制明细表的必填与可编辑属性

本文详细介绍了如何在泛微OA系统中使用JavaScript动态控制明细表字段的必填与可编辑属性。通过主表字段变更事件监听和明细表字段属性批量修改,实现智能化的表单交互,提升用户体验和系统灵活性。文章深入解析了关键API的使用方法,并提供了实战代码示例和最佳实践。

weixin_30955617的博客 549

RabbitMQ之七种消息模型

该笔记大部分搬运B站编程不良人的RabbitMQ,顺便把图文合并记录,便于回顾,仅用于学习! 视频地址:https://www.bilibili.com/video/BV1dE411K7MG 作者真的非常好,别白嫖,记得三连 如有侵权,请联系删除! 1.AMQP协议 2. RabbitMQ七种消息模型 七种消息模型:https://www.rabbitmq.com/getstarted.html 3. RabbitMQ第一个程序 3.1 第一种模式(直连) 在上图的模型中,有以下概念: P:.

Java追求者的博客 1500

爬虫进阶必备:深入理解requests.Session(),提升爬虫效率与稳定性

前两天,有个朋友跟我吐槽,说自己写了个爬虫爬取某个电商网站的商品信息,刚开始跑得好好的,爬了大概几百页之后,突然就开始报错了。HTTP状态码一会儿429,一会儿403,最离谱的是有些页面明明登录了却显示未登录状态。他排查了半天也没找到原因,最后把代码发给我看。 我扫了一眼代码,发现一个典型问题:他每次请求都新建一个requests.Session(),甚至有些请求直接用了requests.get()。这就好比每次进超市都要重新注册会员,每次都重新跟服务器“握手”,不翻车才怪。 其实,这就是我们今天要聊的

2201_76125261的博客 1228

RabbitMQ消息模型详解

RabbitMQ消息模型详解,原理详解,代码展示。其中包括简单消息模型,工作模型,订阅发布模型,订阅模型-Fanout,订阅模型-Direct。

小小张自由—>张有博 1万+

大模型复杂问答能力评测框架:从原理到实践

在人工智能领域,大语言模型(LLM)的评估是衡量其实际应用价值的关键环节。其核心原理在于通过系统化的评测框架,对模型的理解、推理、整合与表达能力进行量化分析。传统的NLP基准测试往往侧重于事实性检索或简单推理,难以全面反映模型在应对多跳推理、隐含条件、长上下文整合等复杂现实任务时的真实性能。因此,专门针对复杂问答设计的评测技术应运而生,其价值在于为模型选型、效果优化和瓶颈诊断提供数据驱动的科学依据。该技术广泛应用于需要深度逻辑判断的业务场景,如智能投顾、法律咨询、医疗诊断等。本文聚焦的`tan92hl/Co

weixin_28679635的博客 362

Simulink进行无人机飞行力学建模与仿真

摘要:本文详细介绍了使用MATLAB/Simulink进行四旋翼无人机飞行力学建模与仿真的步骤。内容包括准备工作、动力学方程概述、模型构建(使用State-Space或Simscape Multibody)、可选控制器设计、仿真参数配置及结果分析。教程强调理解飞行力学原理和坐标系转换的重要性,建议根据需求选择模型复杂度,并推荐查阅学术文献获取更深入的建模方法。通过本教程,读者可掌握无人机动力学建模基础,为控制系统开发和性能优化奠定基础。

amy_mhd的博客 272

RabbitMQ的消息模型

RabbitMQ的消息模型

Qgchun. 1202

PCIe 全解析笔记:从协议本质到工程实现

学习 PCIe,最容易陷入的误区是直接跳进协议手册(Base Spec 1300 多页),然后在 TLP 字段、LTSSM 状态、Ordering Rules 中迷失方向。正确的思维路径历史维度:从 PCI 到 PCIe,解决了什么核心矛盾?抽象维度:协议栈分层的真正意图是什么?工程维度:高速串行链路面临哪些物理挑战?协议如何应对?系统维度:作为 CPU 与外设的"动脉",PCIe 如何融入整个计算机体系?带着这四个视角去看每一个细节,知识才能内化为认知。

m0_46644103的博客 261

看完RabbitMQ了的几种消息模型,我对RabbitMQ有了新的认识

本篇文章将记录和分享剩下的RabbitMQ几种消息模型相关知识点。

小威的博客 2万+

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【Rabbitmq的消息模型】

如上模型,如果是循环的分发方式,Consumer-1一次性被分到的消息为1,3,5号消息,Consumer-2一次性被分到的消息为2,4,6号消息。如果开启消息自动确认,那么一旦MQ把消息发送给消费者,那么该消息就会立即标记为删除。例如,有编号1-10的消息在MQ中,同时存在两个消费者,则消费者A分到的消息为1,3,5,7,9,消费者B分到的消息为2,4,6,8,10。的分发消息的方式,消费能力强的消费者就会被分到更多的消息,消费能力弱的消费者就会被分到更少的消息,该方式需要作额外设置。

m0_50116974的博客 1798

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【RabbitMQ】常用消息模型详解

本文涉及AMQP协议的回顾、RabbitMQ支持的消息模型概述、以及其中Direct模型、WorkQueue模型、Fanout模型、Routing模型、Topic模型的详细介绍与使用

十八岁讨厌编程的博客 3643

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

linux系统消息中间件工具RabbiMQ集群

linux系统消息中间件工具RabbiMQ集群

析木的博客 881

浅谈消息队列的几种消息模型实现

MQ发展到现在共有两种模型:队列模型、发布-订阅模型 队列模型 它允许多个生产者往同一个队列发送消息。但多个消费者之间是竞争的关系,也就是说一条消息只能被其中一个消费者接收到,读完即被删除。 发布-订阅模型 如果需要将一份消息数据分发给多个消费者,并且每个消费者都要求收到全量的消息,队列模型是无法满足这个需求的。 一个可行的方案是:为每个消费者创建一个单独的队列,让生产者发送多份。这种做法比较笨,而且同一份数据会被复制多份,也很浪费空间。而且还有一个问题,生产者必须要知道有多少个消费者,为每个消费者单独发

小生的博客 1035

消息队列之RabbitMQ的五种消息模型,及如何保证可靠消息最终一致性

消息队列(Message Queue,简称MQ):是在消息的传输过程中保存消息的容器,用于分布式系统之间进行通信。MQ的选型和对比在讲RabbitMQ之前先说一下AMQP,即 Advanced Message Queuing Protocol(高级消息队列协议),是一个网络协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。2006年,AMQP规范发布。类比HTTP。

Tobenumerator的博客 1万+

RabbitMQ 保证消息不丢失的几种手段

我们通过分析消息从生产者发送消息到消费者消费消息的全过程,得出了消息可能丢失的几种场景,并给出了相应的解决方案,如果需要保证消息在整条链路中不丢失,那就需要生产端、mq自身与消费端共同去保障。生产端:对生产的消息进行状态标记,开启confirm机制,依据mq的响应来更新消息状态,使用定时任务重新投递超时的消息,多次投递失败进行报警。mq自身:开启持久化,并在落盘后再进行ack。如果是镜像部署模式,需要在同步到多个副本之后再进行ack。

zhiyikeji的博客 6165

RabbitMQ消息模型及常见问题分析

RabbitMQ消息模型及常见问题分析 如何保证RabbitMQ的高可用 如何保证消息不被重复消费(消息幂等性问题) 如何保证消息的可靠性传输 如何保证消息的顺序性 如何解决消息队列的延时以及过期失效

weixin_44491927的博客 2547

RabbitMQ的几种消息确认机制详细介绍

本篇文章将详细介绍RabbitMQ的几种消息确认机制,面试必问的地方,感兴趣的大佬可以看下。

小威的博客 3万+

RabbitMQ之五种消息模型

虚拟主机:类似于mysql中的database。他们都是以“/”开头。

qq_57907966的博客 2412

消息队列RabbitMQ之五种消息模型

在RabbitMQ的官方教程中,RabbitMQ为我们提供了6中消息模型,不过第6种是RPC(远程调用),不是MQ(消息队列),所以RabbitMQ真正的消息模型只有5种。

千里之行,始于足下 2482

RabbitMQ支持的消息模型

目录 1.什么是MQ 1.2 MQ有哪些 1.3不同MQ特点 2 RabbitMQ AMQP协议 1 RabbitMQ支持的消息模型 4.2引入依赖 4.3第一种模型(直连) 1.开发生产者 2.开发消费者 4.4RabbitMQ中连接工具类封装 4.5细节 4.6第二种模型(work quene) 1.定义: 2.角色: 3.生产者: 4.消费者 创建2个: // 区别是是否带下面这个线程休眠代码 5.总结: 6.缺点: 5.第三种模型(fanout| 广播) 1

Ciel_Y的博客 2756

RabbiMQ讲解三topic消息模式

前情回顾 上一章,我们说了如果不指定exchange就会默认的exchange。而默认的exchange的交换类型是direct。也就是说只有RoutingKey和消息队列的名称完全一致的情况下,exchange(交换机)才会将消息转发到消息队列中。 这一篇我们说一下topic消息模式。 topic exchange topic是可以根据RoutingKey的规则,将一个消息转发到多个消息队列中。...

田培融的博客 1405
上一篇: Java 线程和操作系统的线程有啥区别?
下一篇: 带你解读Redisson分布式锁的源码
JavaShark
博客等级 码龄4年 184粉丝 438原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值