小菜最近用到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());

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

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

  1. RabbitMQ之五种消息模型

    首先什么是MQ MQ全称是Message Queue,即消息对列!消息队列是典型的:生产者.消费者模型.生产者不断向消息队列中生产消息,消费者不断的从队列中获取消息.因为消息的生产和消费都是异步的,而 ...

  2. RabbitMQ消息的交换

    消息的交换 目录 RabbitMQ-从基础到实战(1)— Hello RabbitMQ RabbitMQ-从基础到实战(2)— 防止消息丢失 1.简介 在前面的例子中,每个消息都只对应一个消费者,即使 ...

  3. Rabbitmq消息队列(四) 发布订阅

    1.简介 在上篇教程中,我们搭建了一个工作队列,每个任务只分发给一个工作者,在本篇教程中,我们要做的跟之前完全不一样 —— 分发一个消息给多个消费者(consumers).这种模式被称为“发布/订阅” ...

  4. ArcGIS Pro 简明教程(4)工具和模型构建器

    ArcGIS Pro 简明教程(4)工具和模型构建器 by 李远祥 工具箱中的工具 ArcGIS Pro 在1.3版本基本上已经继承了ArcMap的所有工具,而且会不断加入一些它自身才有的工具,例如适 ...

  5. rabbitmq五种消息模型整理

    目录 0. 配置项目 1. 基本消息模型 1.1 生产者发送消息 1.2 消费者获取消息(自动ACK) 1.3 消息确认机制(ACK) 1.4 消费者获取消息(手动ACK) 1.5 自动ACK存在的问 ...

  6. 2013 duilib入门简明教程 -- 事件处理和消息响应 (17)

        界面的显示方面就都讲完啦,下面来介绍下控件的响应.     前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEG ...

  7. duilib教程之duilib入门简明教程17.事件处理和消息响应

    界面的显示方面就都讲完啦,下面来介绍下控件的响应.    前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEGIN_ME ...

  8. RabbitMQ,RocketMQ,Kafka 消息模型对比分析

    消息模型 消息队列的演进 消息队列模型 发布订阅模型 RabbitMQ的消息模型 交换器的类型 direct topic fanout headers Kafka的消息模型 RocketMQ的消息模型 ...

  9. RabbitMQ消息队列系列教程(二)Windows下安装和部署RabbitMQ

    摘要 本篇经验将和大家介绍Windows下安装和部署RabbitMQ消息队列服务器,希望对大家的工作和学习有所帮助! 目录 一.Erlang语言环境的搭建 二.RabbitMQ服务环境的搭建 三.Ra ...

随机推荐

  1. react-router详细解释

    react-router的理解 react的一个插件库,专门用来实现一个SPA应用(单页Web应用(single page web application,SPA)整个应用只有一个完整的页面,点击页面 ...

  2. 配置中心框架IConfCenter

    本篇和大家分享的是一个简易配置中心框架IConfCenter,框架是利用空余时间写的,主要以配置文件+redis存储方式作为数据同步驱动,目前支持的配置文件格式有 .properties 和 .con ...

  3. Spring之旅第三篇-Spring配置详解

    上一篇学习了IOC的概念并初步分析了实现原理,这篇主要学习Spring的配置,话不多说,让我们开始! 一.Bean元素配置 1.1 基本配置 看一个最基本的bean配置 <bean name=& ...

  4. 知识小罐头05(tomcat8请求源码分析 上)

    这一篇我们不看源码,就大概理一下Tomcat内部组成部分!前面花费了两篇博客的篇幅来说说了一般的maven web项目并部署到tomcat运行,其实都是为这篇做铺垫的! 其实我下载了tomcat7,t ...

  5. springboot~configserver里对重要信息进行RSA加密

    简介 参考:https://springcloud.cc/spring-cloud-dalston.html#_encryption_and_decryption_2 RSA非对称加密有着非常强大的安 ...

  6. vue.js移动端配置flexible.js

    前言 最近在用vue做移动端项目,网上找了一些移动端适配的方案,个人觉得手淘团队flexible.js还是比较容易上手,在这里做下总结. 主体 flexible.js适配方案采用rem布局,根据屏幕分 ...

  7. [开发技巧]·Numpy广播机制的深入理解与应用

    [开发技巧]·Numpy广播机制的深入理解与应用 1.问题描述 我们在使用Numpy进行数据的处理时,经常会用到广播机制来简化操作,例如在所有元素都加上一个数,或者在某些纬度上作相同的操作.广播机制很 ...

  8. C++ 编程技巧笔记记录(持续更新)

    C++是博大精深的语言,特性复杂得跟北京二环一样,继承乱得跟乱伦似的. 不过它仍然是我最熟悉且必须用在游戏开发上的语言,这篇文章用于挑选出一些个人觉得重要的条款/经验/技巧进行记录总结. 文章最后列出 ...

  9. Asp.Net Core 轻松学-利用xUnit进行主机级别的网络集成测试

    前言     在开发 Asp.Net Core 应用程序的过程中,我们常常需要对业务代码编写单元测试,这种方法既快速又有效,利用单元测试做代码覆盖测试,也是非常必要的事情:但是,但我们需要对系统进行集 ...

  10. 云HBase发布全文索引服务,轻松应对复杂查询

    云HBase发布了“全文索引服务”功能,自2019年01月25日后创建的云HBase实例,可以在控制台免费开启此“全文索引服务”功能.使用此功能可以让用户在HBase之上构建功能更丰富的搜索业务,不再 ...