RabbitMQ消息模型概览(简明教程)

小菜最近用到RabbitMQ,由于之前了解过其他消息中间件,算是有些基础,所以随手从网上搜了几篇文章,准备大概了解下RabbitMQ的消息模型,没想到网上文章千篇一律,写一大堆内容,就是说不明白到底怎么回事,真是逼小菜写博客…

首先说明本文只适合有消息中间件基础的读者,本文不会讲解基础概念,而是一针见血的指明RabbitMQ该怎么用,告诉读者RabbitMQ能做什么,而不是像网络上其他文章那样花里胡哨抓不住重点。

好了,直入正题。

simple简单队列

这种队列,纯属RabbitMQ搞的一个花样,仅仅是个概念而已!并不是实际的队列类型!他就是在假设某个队列只有一个消费者,也就是说,读者在实际使用中,某个队列傻傻的只用一个消费者去消费,这就叫simple简单队列啦,应用场景极少,一般情况下消费端都会有多个消费者。

Fair dispatch公平分发

这种队列让人一看,有点蒙逼,实际上这个概念非常非常简单,如果读者用过redis的话,这个队列模式很像redis的list用法,只不过redis是拉取模型,而mq是推送模型。

这个公平,可不是说消息平均的发送给消费者,恰恰相反,消费者消费消息的多少,完全取决于消费者的处理能力,能者多劳,相当于消费者主动从mq中取消息,而不是被mq安排消息。

实现上也不难理解,消费端消费数据时,会有一个确认消费完成的动作,mq收到消费完成的通知后,才会继续向该消费者发送消息,因此,如果消费者处理速度快,那么最终mq向它发送的消息就多,如果消费者处理的慢,mq向它发送的消息就少。

在这小菜贴出java代码实现的关键点:

当然,这是消费端代码,仅仅在消费端做处理即可,对于生产端来说是透明的,不需要做任何处理。

Round-robin轮询分发

所谓轮询分发,就是公平分发的退化版,打开自动通知,去掉手动通知,去掉消费端消费条数限制,就是轮询分发啦!!!

其实轮询分发就是利用了自动通知参数,开启了自动通知,mq根据一个简单的规则(比如取模运算),先确定好哪些消息发送给哪些消费者,无论消费者处理能力如何,这些消息都得让你处理,因此每个消费者最终处理的消息数量,是相同的(忽略"消息数量/消费者"不能整除的情况)。

这种模式很明显是有问题的,首先,这种模式不能很好的利用消费端的性能差异,做不到真正意义上的负载均衡,浪费资源;其次(只是猜测),这种模型还有可能造成大量消息堆积在消费者容器中,这是非常危险的,不仅会造成消息丢失,还有可能压垮消费者。

publish_subscribe发布订阅模式

RabbitMQ 中有一个交换机Exchanges的概念,发布订阅就是通过交换机实现的。

交换机的概念非常简单,就是一个转发器,有了交换机之后,生产端先把消息发送到交换机,然后交换机再把消息发送到与其绑定的消息队列,这样就解决了生成端如何把一条消息批量发送到多个消息队列的问题。

交换机本身没有数据存储能力,仅仅是一个代理,可以理解成nginx。

因此,实现发布订阅的关键在于:

·  生产端(发布端)直接发送消息到交换机,而不是具体的消息队列。

·  多个消费端(订阅端)将自己的消息队列绑定到同一个交换机上。

这样就实现了发布订阅。

routing路由模式

路由模式仅仅基于发布订阅搞了一点小事情,在发布订阅模式中,交换机无脑向所有与之绑定的消息队列发送消息,而路由模式对交换机做了一些限制,它指定了一个route key,生产端向交换机发送消息时,指定消息的route key,消费端将消息队列绑定到交换机时,也指定该队列消费的route key,这样一来,交换机就可以根据消息的route key,将该消息转发到绑定(消费)该route key的消息队列。

生产端关键点:

 消费端关键点:

topic主题模式

RabbitMQ又开始搞花样了,咋一看topic小菜还以为是kafka里的topic概念呢,弄的莫名其妙。

主题模式其实就是路由模式的一个加强,而且是非常非常非常简单的一个加强:route key支持通配符。

主题模式和路由模式完全一样,只不过是消费端route key不用写死,增加了一个模糊匹配的功能,这样在某些场景下,消费端就不用逐一绑定所有监听的route key,直接用抽象的通配符表示即可,当然,这是针对消费端的优化,与生产端无关。

关于RabbitMQ的可靠性

消费端的消费可靠性,已经在"Fair dispatch公平分发"章节中做了介绍,即利用手动通知告诉mq消费成功,但通知也有不可达的可能,进而涉及到重发,具体的处理细节,读者自行查阅资料。

生产端的提交可靠性,可以通过mq的回调机制实现,即生产端发送消息时自己维护一份已发送消息的集合,mq收到某条消息之后,会向生产端发送一个接收成功确认(体现在代码中就是回调),然后生产端根据确认消息的唯一id,从自己维护的已发送消息集合中移除该消息,从而确保每条消息都成功发送到了mq。

假如某些消息未成功到达mq,那么就不会有对应消息的确认,最终集合中会有剩余元素(理想情况下是没有的),这些剩余元素,就是发送失败的消息,需要重发。

简单展示下代码关键点( 生产端):

虽然确认机制可以保证消息的可靠性,但是必然带来性能损失,因此到底需不需要开启生产端或消费端的确认机制,需要根据业务场景具体分析。

一些注意事项

RabbitMQ的Connection是昂贵的,但Channel是廉价的,在多线程环境下,尽量创建少数Connection,然后在每个Connection中创建多个Channel,利用Channel实现Connection复用,从而提高系统性能。很像Java NIO里的Selector到Channel的多路复用。

生产端发送消息时,同一个Channel的basicPublish方法并不是线程安全的,因此更加体现出多Channel的重要性。如果生产端需要使用多线程发送消息,那么必须创建多个Channel,每一个线程单独使用一个Channel,但是这些Channel可以来自同一个Connection。假如线程数量过多,那么也不可以无限制的创建Channel,需要使用Channel Pool(连接池)的思路去控制并发。

对于同一个Channel而言,发送消息和接受消息是互不影响的,可以进行并发操作。

 

吐槽

最后吐槽一下RabbitMQ客户端API设计的真难用,同一个API竟然通过参数值重载,就比如向消息队列发送消息是这样:

channel.basicPublish("","队列名称", null, message.getBytes());

然后向交换机发消息是这样:

channel.basicPublish("交换机名称","route key", null, message.getBytes());

同一个方法,第二个参数的含义,竟然是通过第一个参数是否为空决定的,厉害了~

原文地址:https://www.cnblogs.com/iyangyuan/p/9575683.html

时间: 2024-08-01 14:39:24

RabbitMQ消息模型概览(简明教程)的相关文章

Python实现RabbitMQ中6种消息模型

RabbitMQ与Redis对比 ? RabbitMQ是一种比较流行的消息中间件,之前我一直使用redis作为消息中间件,但是生产环境比较推荐RabbitMQ来替代Redis,所以我去查询了一些RabbitMQ的资料.相比于Redis,RabbitMQ优点很多,比如: 具有消息消费确认机制 队列,消息,都可以选择是否持久化,粒度更小.更灵活. 可以实现负载均衡 RabbitMQ应用场景 异步处理:比如用户注册时的确认邮件.短信等交由rabbitMQ进行异步处理 应用解耦:比如收发消息双方可以使用

rabbitmq五种消息模型整理

目录 0. 配置项目 1. 基本消息模型 1.1 生产者发送消息 1.2 消费者获取消息(自动ACK) 1.3 消息确认机制(ACK) 1.4 消费者获取消息(手动ACK) 1.5 自动ACK存在的问题 1.6 演示手动ACK 2. work消息模型 2.1 生产者 2.2 消费者1 2.3 消费者2 2.4 能者多劳 3. 订阅模型分类 4. 订阅模型-Fanout 4.1 生产者 4.2 消费者1 4.3 消费者2 4.4 测试 5. 订阅模型-Direct 5.1 生产者 5.2 消费者1

Vbs 脚本编程简明教程之一

-为什么要使用 Vbs ? 在 Windows 中,学习计算机操作也许很简单,但是很多计算机工作是重复性劳动,例如你每周也许需要对一些计算机文件进行复制.粘贴.改名.删除,也许你每天启动 计算机第一件事情就是打开 WORD ,切换到你喜爱的输入法进行文本编辑,同时还要播放优美的音乐给工作创造一个舒心的环境,当然也有可能你经常需要对文本中的某 些数据进行整理,把各式各样的数据按照某种规则排列起来--.这些事情重复.琐碎,使人容易疲劳. 第三方软件也许可以强化计算机的某些功能,但是解决这些重复劳动往

TR069协议向导——一个帮助你了解TR069协议的简明教程(一)

您也能够到下面地址下载: http://download.csdn.net/source/993034 1.为什么须要TR069 随着VoIP.IPTV等越来越多IP终端设备的普及(尤其在家庭中的普及),大量设备的配置和维护变得越来越困难,大大提高了网络产品运营商的成本,传统的基于SNMP的网管系统面对众多的终端设备时显得力不从心,限制了宽带接入市场的发展速度和规模.TR069定义了一套全新的网管体系结构,包含"管理模型","交互接口","管理參数&quo

rabbitmq消息队列

rabbitmq消息队列 在之前的教程中,我们创建了一个简单的日志系统.我们能够向许多交换器转发日志消息. 在本教程中,我们将添加一个功能--我们让它仅仅接收我们感兴趣的日志类别.举例:我们 实现仅将严重级别的错误日志写入磁盘(为了节省磁盘空间),其余日志级别的日志直接打印到控制台. 绑定 之前的章节中我们已经创建过绑定,你可能还会记得: 1 2 3 4 5 6 err = ch.QueueBind(   q.Name, // queue name   "",     // routi

docker简明教程(二)

前言这篇博文承接我的上一篇<docker简明教程一> http://9399369.blog.51cto.com/9389369/1758576 相对于上一篇来说这篇所讲到的知识会高深一点因为学习的过程不就是一步步的由简单到复杂嘛但是我的风格没变用简单的文字让朋友们学习高深的docker技术.如果觉得我写的好的话顶我上推荐希望能让跟多人看到.学习和受益. 二十二.Docker导出容器到本地文件 不管是容器不是处于运行状态都可以导出 首先查看那容器状态 [[email protected] ~]

Gevent简明教程

Gevent简明教程 发表于 2015-11-28 |  分类于 技术| |  阅读次数 5159 前述 进程 线程 协程 异步 并发编程(不是并行)目前有四种方式:多进程.多线程.协程和异步. 多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库 多线程编程python中有Thread和threading 异步编程在linux下主+要有三种实现select,poll,epoll 协程在python中通常会说到yield,关于协程的库主要有gre

Lisp简明教程

此教程是我花了一点时间和功夫整理出来的,希望能够帮到喜欢Lisp(Common Lisp)的朋友们.本人排版很烂还望多多海涵! <Lisp简明教程>PDF格式下载 <Lisp简明教程>ODT格式下载 具体的内容我已经编辑好了,想下载的朋友可以用上面的链接.本人水平有限,如有疏漏还望之处(要是有谁帮我排排版就好了)还望指出!资料虽然是我整理的,但都是网友的智慧,如果有人需要转载,请至少保留其中的“鸣谢”页(如果能有我就更好了:-)). Lisp简明教程 整理人:Chaobs 邮箱:[

Smarty教程1.引擎定义2.主要优点3.简明教程4.使用判断5.循环数组6.常见问题8.解释程序

Smarty是一个php模板引擎.更准确的说,它分开了逻辑程序和外在的内容,提供了一种易于管理的方法.可以描述为应用程序员和美工扮演了不同的角色,因为在大多数情况下 ,他们不可能是同一个人.例如,你正在创建一个用于浏览新闻的网页,新闻标题,标签栏,作者和内容等都是内容要素,他们并不包含应该怎样去呈现.在Smarty的程序里,这些被忽略了.模板设计者们编辑模板,组合使用html标签和模板标签去格式化这些要素的输出(html表格,背景色,字体大小,样式表,等等).有一天程序员想要改变文章检索的方式(