RabbitMQ基础和解疑
一、基础概念
1. Producer:生产者,就是投递消息的一方
消息一般可以包含2个部分:消息体和标签(Label)。消息体也可以称之为payload,在实际应用中,消息体一般是一个带有业务逻辑结构的数据,比如一个JSON字符串。当然可以进一步对这个消息体进行序列化操作。消息的标签用来表述这条消息,比如一个交换器的名称和一个路由键。生产者把消息交由RabbitMQ,RabbitMQ之后会根据标签把消息发送给感兴趣的消费者(Consumer)。
2. Consumer:消费者,就是接收消息的一方
消费者连接到RabbitMQ服务器,并订阅到队列上。当消费者消费一条消息时,只是消费消息的消息体(payload)。在消息路由的过程中,消息的标签会丢弃,存入到队列中的消息只有消息体,消费者也只会消费到消息体,也就不知道消息的生产者是谁,当然消费者也不需要知道
3. Queue:队列,是RabbitMQ的内部对象,用于存储消息
RabbitMQ中消息都只能存储在队列中,这一点和Kafka这种消息中间件相反。Kafka将消息存储在topic(主题)这个逻辑层面,而相对应的队列逻辑只是topic实际存储文件中的位移标识。RabbitMQ的生产者生产消息并最终投递到队列中,消费者可以从队列中获取消息并消费。
多个消费者可以订阅同一个队列,这时队列中的消息会被平均分摊(Round-Robin,即轮询)给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理,如图2-4所示。
图2-4 多个消费者
RabbitMQ不支持队列层面的广播消费,如果需要广播消费,需要在其上进行二次开发,处理逻辑会变得异常复杂,同时也不建议这么做
4. Exchange:交换器。
生产者将消息发送到Exchange ,由交换器将消息路由到一个或者多个队列中。如果路由不到,或许会返回给生产者,或许直接丢弃
生产者可以在发送消息给交换器时,通过指定RoutingKey来决定消息流向哪里。
换言之,交换机只是起一个路由作用,可以通过交换机路由到多个队列。即一个生产者可以将消息同时写到多个队列。
RabbitMQ常用的交换器类型有direct、topic、headers、fanout这四种。
AMQP协议里还提到另外两种类型:System和自定义,这里不予描述。对于这四种类型下面一一阐述。
4.1 direct 类型
路由规则也很简单,它会把消息路由到那些BindingKey和RoutingKey完全匹配的队列中。
channel.QueueBind(queueName, exchangeName, bindingKey, null);
channel.BasicPublish(exchangeName, bindingKey, props, Encoding.UTF8.GetBytes(i.ToString()));
对于direct 类型 ** ,只要上图中的2行使用的bindingKey
是相同的 , 就能把消息保存到对应的队列;
如果有多个队列,使用使用完全相同的交换机名和 bindingKey , 则还会把消息保存到这些queue上。
如果在发送消息的时候设置路由键为“warning” ,消息会路由到Queue1和Queue2。
如果在发送消息的时候设置路由键为“info”或者“debug”,消息只会路由到Queue2。
如果以其他的路由键发送消息,则消息不会路由到这两个队列中。
4.2 topic 类型
RoutingKey 为一个点号“.”分隔的字符串(被点号“.”分隔开的每一段独立的字符串称为一个单词),如“com.rabbitmq.client”、“java.util.concurrent”、“com.hidden.client”;
BindingKey中可以存在两种特殊字符串 星符号 "* " 和 井符号"#",用于做模糊匹配,其中 "* " 用于匹配一个单词,"#" 用于匹配多规格单词(也可以是零个)。
如“log.*”能与“log.warn”匹配,无法与“log.warn.timeout”匹配;但是“log.#”能与上述两者匹配。
●路由键为“com.rabbitmq.client”的消息会同时路由到Queue1和Queue2;
●路由键为“java.rabbitmq.demo”的消息只会路由到Queue1中;
●路由键为“com.hidden.client”的消息只会路由到Queue2中;
●路由键为“com.hidden.demo”的消息只会路由到Queue2中;
路由键为“java.util.concurrent”的消息将会被丢弃或者返回给生产者(需要设置mandatory参数),因为它没有匹配任何路由键。
4.3 fanout 类型
它会把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中。即无视RoutingKey和BindingKey的匹配规则。
4.4 headers类型
headers类型的交换器性能会很差,而且也不实用,基本上不会看到它的存在。
4.5 性能大比拼
性能排序:fanout > direct >> topic。比例大约为11:10:6
4.6 RoutingKey 和 BindingKey 傻傻分不清楚 ?
5 Broker(代理)
对于RabbitMQ来说,一个RabbitMQ Broker可以简单地看作一个RabbitMQ服务节点,或者RabbitMQ服务实例。大多数情况下也可以将一个RabbitMQ Broker看作一台RabbitMQ服务器。
6 整体架构
(图2)
(图2)
二、工作队列
一般情况下生产者往队列里插入数据时速度是比较快的,但是消费者消费数据往往涉及到一些业务逻辑处理导致速度跟不上生产者生产数据。
因此如果一个生产者对应一个消费者的话,很容易导致很多消息堆积在队列里。这时,就得使用工作队列了。一个队列有多个消费者同时消费数据。
工作队列有两种分发数据的方式:轮询分发(Round-robin) 和 公平分发(Fair dispatch)
1. 轮询分发(Round-robin)
队列给每一个消费者发送数量一样的数据。如: 生产者(Send)生产10条数据,消费者1(Receive1)接收数据并假设处理业务逻辑1s,消费者2(Receive2)接收数据并假设处理业务逻辑2s
两个消费者得到的数据量一样的。消费者1会先执行完,消费者2会后执行完。并不会因为两个消费者处理数据速度不一样使得两个消费者取得不一样数量的数据。这种分发方式存在着很大的隐患。
2. 公平分发(Fair dispatch):
消费者设置每次从队列中取一条数据,并且消费完后手动应答,继续从队列取下一个数据(推荐) 。
与轮询分发不同的是,当每个消费都设置了每次只会从队列取一条数据时,并且关闭自动应答,在每次处理完数据后手动给队列发送确认收到数据。这样队列就会公平给每个消息费者发送数据,消费一条再发第二条,而且可以在管理界面中看到数据是一条条随着消费者消费完从而减少的,并不是一下子全部分发完了。显然公平分发更符合系统设计。
参考:
《RabbitMQ实战指南》
官网: https://www.rabbitmq.com/tutorials/tutorial-one-dotnet.html
介绍:https://zhuanlan.zhihu.com/p/359119600
觉得还不错,可以支持一下
RabbitMQ基础和解疑的更多相关文章
- RabbitMQ基础知识
RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...
- 转:RabbitMQ基础知识
RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...
- RabbitMQ基础知识详解
什么是MQ? MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中 ...
- RabbitMQ基础教程之基本使用篇
RabbitMQ基础教程之基本使用篇 最近因为工作原因使用到RabbitMQ,之前也接触过其他的mq消息中间件,从实际使用感觉来看,却不太一样,正好趁着周末,可以好好看一下RabbitMQ的相关知识点 ...
- RabbitMq基础教程之基本概念
RabbitMq基础教程之基本概念 RabbitMQ是一个消息队列,和Kafka以及阿里的ActiveMQ从属性来讲,干的都是一回事.消息队列的主要目的实现消息的生产者和消费者之间的解耦,支持多应用之 ...
- 转 RabbitMQ 基础概念及 Spring 的配置和使用 推荐好文 举例讲解
从不知道到了解—RabbitMQ 基础概念及 Spring 的配置和使用 原理同上 请求地址:http://localhost:8080/home?type=3&routing_key=myO ...
- RabbitMQ基础组件和SpringBoot整合RabbitMQ简单示例
交换器(Exchange) 交换器就像路由器,我们先是把消息发到交换器,然后交换器再根据绑定键(binding key)和生产者发送消息时的路由键routingKey, 按照交换类型Exchange ...
- C#RabbitMQ基础学习笔记
RabbitMQ基础学习笔记(C#代码示例) 一.定义: MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开发).MQ是一种应用程序对应用程序的通信方法. ...
- RabbitMQ基础教程之Spring&JavaConfig使用篇
RabbitMQ基础教程之Spring使用篇 相关博文,推荐查看: RabbitMq基础教程之安装与测试 RabbitMq基础教程之基本概念 RabbitMQ基础教程之基本使用篇 RabbitMQ基础 ...
- RabbitMQ基础教程之使用进阶篇
RabbitMQ基础教程之使用进阶篇 相关博文,推荐查看: RabbitMq基础教程之安装与测试 RabbitMq基础教程之基本概念 RabbitMQ基础教程之基本使用篇 I. 背景 前一篇基本使用篇 ...
随机推荐
- ArcObjects SDK开发 006 ICommand和ITool接口
1.ICommand接口 ICommand接口是插件协议之一,继承该接口的类都可以成为命令.即点击一下执行,不主动与宿主发生鼠标和键盘交互.该接口包含的重要成员如下表所示. 序号 名称 类型 描述 1 ...
- 打印菱形-java
public class WeekendDemo01 { /** 打印菱形 * * * *** * ***** * *** * * */ public static void main(String[ ...
- Datawhale组队学习_Task03:详读西瓜书+南瓜书第4章
第4章 决策树 4.1 基本流程 #输入:训练集D={${(x_1,y_1),(x_2,y_2),...,(x_m,y_m)}$}; #属性集A=${{a_1,a_2,...,a_d}}$. #过程: ...
- CompletionService 使用小结
本文为博主原创,转载请注明出处: 实现异步任务时,经常使用 FutureTask 来实现:一个简单的示例代码如下: public static void main(String[] args) thr ...
- Azure DevOps 中自定义控件的开发
Azure DevOps 插件: Field Unique Control https://github.com/smallidea/azure-devops-extension-custom-con ...
- 把时间沉淀下来 | Kagol 的 2022 年终总结
现代管理学之父德鲁克在其经典著作<卓有成效的管理者>中对时间有一段精妙的论述,其要点如下: 时间是一项限制因素,任何生产程序的产出量,都会受到最稀有资源的制约,而时间就是其中最稀有的资源. ...
- ATM购物车项目总结
目录 项目实现思路 ATM项目 优先实现功能 拆分函数 项目路径展示 项目启动文件 start.py 配置文件 setting.py 日志配置字典 日志函数 展示层 src.py 用户注册 获取用户输 ...
- python模块的含义
目录 模块简介 模块的本质 python模块的历史 python模块的表现形式 模块的分类 导入模块的两种句式 强调 import句式 import流程推导 练习 from...import...句式 ...
- Go语言性能剖析利器--pprof实战
作者:耿宗杰 前言 关于pprof的文章在网上已是汗牛充栋,却是千篇一律的命令介绍,鲜有真正实操的,本文将参考Go社区资料,结合自己的经验,实战Go程序的性能分析与优化过程. 优化思路 首先说一下性能 ...
- vue中点按钮回到顶部,和elementUI中置顶按钮的实现
一般做pc项目都会遇到侧边小按钮点击回到顶部的功能,现在记录一下项目中的实现方法 一.结合动画效果实现 <li class="defa_bt" @click="hd ...