RabbitMQ官网: http://www.rabbitmq.com/
Erlang官网:https://www.erlang.org
友情提示:RabbitMQ基于Erlang语言开发的,要想使用RabbitMQ的话,需要先安装Erlang环境

1.RabbitMQ是什么

  RabbitMQ是消息代理:它接受并转发消息。可以将它视为邮局:当你投递邮件到一个邮箱,邮递员终究会将邮件递交给你的收件人。以此类推,RabbitMQ可以是一个邮箱,一个邮局和一个邮递员。

  RabbitMQ与邮局之间的主要区别在于,它不处理纸张,而是接收,存储和转发数据消息的二进制数据。

2.RabbitMQ的组成

  2.1 生产者(producer)与消费者(consumer)

  生产者与消费者是RabbitMQ通信过程中的两个重要的角色,相当于邮件的发送方与接收方,而RabbitMQ充当的角色就是传递消息的第三方,也就是说它是不能产生数据的。在实际应用中,生产者和消费者也是可以角色互相转换的,所以当我们应用程序连接到 RabbitMQ 服务器时,必须要明确我是生产者还是消费者。

  2.2 连接(Connections)

  生产者生产消息之后,发布到RabbitMQ之前,需要先连接RabbitMQ服务器吧,RabbitMQ支持的所有协议都是基于TCP的,并且为了提高效率而采用长期连接(每个协议操作不会打开新连接)。一个客户端库连接使用单个TCP连接。

  2.3 通道(Channels)

  建立完连接之后,客户端会基于该TCP连接的基础之上,开辟一条AMQP通道,客户端执行的每个协议操作都在通道上发生,通道存在于连接中,而不是单独存在的。关闭连接后,其上的所有通道也将关闭。

  我们也可以在一条连接中开辟一条或多条AMQP通道,每条通道都会有一个唯一的ID来确保通道之间互不干预

  2.4 队列(Queues)

  队列是RabbitMQ服务器中消息的终点,类似于一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。

  2.5 交换机(Exchanges)

  交换机用于接收生产者发送的消息,并且能处理消息,例如将消息递交给某个队列、递交给所有队列、或者将消息丢弃,它主要应用的有三种类型:

 a、Fanout:广播(扇形),将消息交给所有绑定到交换机的队列

 b、Direct:定向(直连),把消息交给符合指定routing_key 的队列

 c、Topic:通配符(主题),把消息交给符合routing pattern(路由模式) 的队列

补充:交换机只负责转发消息,不具备存储消息的能力,如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!

3.RabbitMQ的消息模式

  3.1 simple简单模式



  生产者与消费者为一对一的关系,一条消息只能被一个消费者消费,如果此时没有消费者,那么消息会被暂时缓存在queue中,直至被消费

  3.2 work工作模式



  在work模型下,生产者与消费者为一对多的关系,多个消费者可以绑定到一个队列,共同消费队列中的消息

补充:消息一旦被消费者接收,队列中的消息就会被删除,所有不会存在消息重复消费的问题,即每条消息只能被多个消费者中的其中一个消费者消费
  问题1:在多个消费者的情况下,消息如何分配

  queue可以实现负载均衡,生产者将消息放入queue中后,RabbitMQ会通过轮询的方式,实现消息的分配

  问题2:RabbitMQ怎么知道消息被接收了呢

  通过消息确认机制(Acknowlege)实现。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。不过这种回执ACK分两种情况:

  • 自动ACK:消息一旦被接收,消费者自动发送ACK
  • 手动ACK:消息接收后,不会发送ACK,需要手动调用
问题3:如何使用自动和手动ACK?

  这就要取决于消息的重要性,如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便,反之,如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK,否则接收消息后就自动ACK,RabbitMQ就会把消息从队列中删除,如果此时消费者宕机,那么消息就丢失了。

  3.3 订阅模型-Fanout



  X表示交换机;在广播模式下,消息发送流程是这样的:

  • 1) 可以有多个消费者
  • 2) 每个消费者有自己的queue(队列)
  • 3) 每个队列都要绑定到Exchange(交换机)
  • 4) 生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
  • 5) 交换机把消息发送给绑定过的所有队列
  • 6) 队列的消费者都能拿到消息。实现一条消息被多个消费者消费

  3.4 订阅模型-Direct

在Direct模型下:

  • 1) 队列与交换机的绑定,不能是任意绑定了,而是要指定一个routing_key(路由key)
  • 2) 消息的发送方在 向 Exchange发送消息时,也必须指定消息的 routing_key
  • 3) Exchange不再把消息交给每一个绑定的队列,而是根据消息的routing_key进行判断,只有队列的routing_key与消息的 routing_key完全一致,才会接收到消息



    图解:
  • P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
  • X:Exchange(交换机),接收生产者的消息,然后把消息递交给 与routing_key完全匹配的队列
  • C1:消费者,其所在队列指定了需要routing_key 为 error 的消息
  • C2:消费者,其所在队列指定了需要routing_key 为 info、error、warning 的消息

  3.5 订阅模型-Topic

  Topic类型的Exchange与Direct相比,都是可以根据routing_key把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定routing_key的时候使用通配符!通配符规则:

  #:可以替代零个或多个单词。

  *:可以代替一个单词

解释:routing_key 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert



图解:

  • C1:消费者,其所在队列Q1绑定了*.orange.*的routing_key,它能匹配到以orange为中心,前后各一个单词的路由,例如:item.orange.insert,但是该item.orange.insert.one路由就不能被匹配
  • C2:消费者,其所在队列Q2绑定了lazy.#的routing_key,它能匹配到任何以lazy.开头的路由
在上面交换机中,提到了消息丢失的问题,那么哪种情况下消息会丢失,如何处理
  • 1) 生产者弄丢了数据。生产者将数据发送到 RabbitMQ 的时候,可能数据就在半路给搞丢了,比如:因为网络问题。

    解决方案:使用发送方确认机制。发送方确认机制是指生产者将信道设置成confirm(确认)模式,一旦信道进入confirm模式,所有在该信道上面发布的消息都会被指派一个唯一的ID(从1开始),一旦消息被投递到RabbitMQ服务器之后,RabbitMQ就会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID),这就使得生产者知晓消息已经正确到达了目的地了。
  • 2) RabbitMQ 弄丢了数据。比如:MQ宕机了

    解决方案:RabbitMQ 的消息默认存放在内存上面,如果不特别声明设置,消息不会持久化保存到硬盘上面的,如果MQ宕机,消息就会丢失。

    我们可以对消息进行持久化处理,要将消息持久化,前提是:队列、Exchange都持久化
//获取连接
Connection connection = ConnectionUtil.getConnection();
//建立通道
Channel channel = connection.createChannel();
//交换机持久化 ,第三个参数代表是否持久化
channel.exchangeDeclare(EXCHANGE_NAME,"EXCHANGE_TYPE",true);
//队列持久化 ,第二个参数代表是否持久化
channel.queueDeclare(QUEUE_NAME,true,false,false,null);
//消息持久化 ,第三个参数代表是否持久化
channel.basicPublish(EXCHANGE_NAME,routing_key,MessageProperties.PERSISTENT_TEXT_PLAIN,MESSAGE_CONTENT.getBYtes());
  • 3) 消费端弄丢了数据。刚接收到消息,还没处理,结果进程挂了,比如:重启了。

    解决方案:使用消费者的ACK机制。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。如果这个消费者挂掉没有发送应答,RabbitMQ会理解为这个消息没有被处理,然后交给另一个消费者去重新处理。这样,你就可以确认即使消费者偶尔挂掉也不会丢失任何消息了。

手把手带你了解消息中间件(2)——RabbitMQ的更多相关文章

  1. 手把手带你了解消息中间件(3)——RocketMQ

    一.RocketMQ简介   RocketMQ作为一款纯java.分布式.队列模型的开源消息中间件,支持事务消息.顺序消息.批量消息.定时消息.消息回溯等. 二.RocketMQ架构   如图所示为R ...

  2. [.Net] 手把手带你将自己打造的类库丢到 NuGet 上

    手把手带你将自己打造的类库丢到 NuGet 上 序 我们习惯了对项目右键点击“引用”,选择“管理NuGet 程序包”来下载第三方的类库,可曾想过有一天将自己的打造的类库放到 NuGet 上,让第三者下 ...

  3. 手把手带你做一个超炫酷loading成功动画view Android自定义view

    写在前面: 本篇可能是手把手自定义view系列最后一篇了,实际上我也是一周前才开始真正接触自定义view,通过这一周的练习,基本上已经熟练自定义view,能够应对一般的view需要,那么就以本篇来结尾 ...

  4. Android性能优化:手把手带你全面实现内存优化

      前言 在 Android开发中,性能优化策略十分重要 本文主要讲解性能优化中的内存优化,希望你们会喜欢 目录   1. 定义 优化处理 应用程序的内存使用.空间占用 2. 作用 避免因不正确使用内 ...

  5. Android:手把手带你深入剖析 Retrofit 2.0 源码

    前言 在Andrroid开发中,网络请求十分常用 而在Android网络请求库中,Retrofit是当下最热的一个网络请求库 今天,我将手把手带你深入剖析Retrofit v2.0的源码,希望你们会喜 ...

  6. [转帖]从零开始入门 K8s | 手把手带你理解 etcd

    从零开始入门 K8s | 手把手带你理解 etcd https://zhuanlan.zhihu.com/p/96721097 导读:etcd 是用于共享配置和服务发现的分布式.一致性的 KV 存储系 ...

  7. 手把手带你阅读Mybatis源码(三)缓存篇

    前言 大家好,这一篇文章是MyBatis系列的最后一篇文章,前面两篇文章:手把手带你阅读Mybatis源码(一)构造篇 和 手把手带你阅读Mybatis源码(二)执行篇,主要说明了MyBatis是如何 ...

  8. GitHub 热点速览 Vol.26:手把手带你做数据库

    作者:HelloGitHub-小鱼干 摘要:手把手带你学知识,应该是学习新知识最友好的姿势了.toyDB 虽然作为一个"玩具"项目不能应用在实际开发中,但通过它你可以了解到如何制作 ...

  9. 手把手带你体验鸿蒙 harmonyOS

    wNlRGd.png 前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 image.png 一.为什么要尝鲜 harmonyos? wNlfx ...

随机推荐

  1. 通过GDB重新获得进程的输出

    有时通过SecureCRT或者Putty远程ssh到主机上执行某个进程,因长时间没有交互导致ssh断链,此时该进程由init进程收留.该进程的输出也就无法获得了. 这种情况下,可以利用gdb重新获得该 ...

  2. 因为 Java 和 Php 在获取客户端 cookie 方式不同引发的 bug

    遇到个 Java 和 Php 在获取客户端 cookie 方式不同导致跨系统的问题.所以写了这篇博客梳理下相关知识. 实验 下面通过两个简单的实验,来看Java和Php在获取web请求中的cookie ...

  3. TP-admin即基于ThinkPHP5拿来即用高性能后台管理系统

    TP-Admin即基于ThinkPHP5的web后台管理系统(总结一套自己的后台管理系统,方便自己后续的项目开发.) 主要特性:自适应手机端.支持国际化.吸取其他CMF框架优点.多站点部署.日志记录. ...

  4. uni-app中使用Echarts绘画图表

    enmnm...一般会使用npm下载echarts这个包,但是不知道是我自己的配置问题还是别的原因,一直出不来图线, 于是,把Hello uni-app模板里的那个组件抱过来,然后,成了! 首先, 1 ...

  5. 记一次sublime text3更新 注册码失效问题和永久解决~

    前言: 一段时间不用sublime,打开提示我更新,不知怎么想的鬼使神差给点了~ 然后喵喵喵??? 取消 一会又出来了 受不了啦 搞事开整~ 正文: 本想直接找个注册码完事,奈何好多都用不了,想着再更 ...

  6. kwargs.pop是什么意思

    pop()函数一般用来删除list列表的末尾元素,同样,kwargs.pop()用来删除关键字参数中的末尾元素,比如:kwargs = {'Michael': 95, 'Bob': 75, 'Trac ...

  7. 2017年NOIP普及组复赛题解

    题目涉及算法: 成绩:入门题: 图书管理员:模拟: 棋盘:最短路/广搜: 跳房子:RMQ/二分答案/DP(本人解法). 成绩 题目链接:https://www.luogu.org/problemnew ...

  8. 洛谷P1809 过河问题 经典贪心问题

    作者:zifeiy 标签:贪心 题目链接:https://www.luogu.org/problem/P1809 我们假设第 \(i\) 个人过河的耗时是 \(t[i]\) ,并且 \(t[i]\) ...

  9. 机器学习——集成学习之Bagging

    整理自: https://blog.csdn.net/woaidapaopao/article/details/77806273?locationnum=9&fps=1 随机森林 1.随机森林 ...

  10. ZR979B. 【十联测 Day 9】唯一睿酱

    ZR979B. [十联测 Day 9]唯一睿酱 题目大意: 给定一个数组\(r_i\),表明对于第\(i\)个数来说,他是\([max(1,i - r_i),min(n,i+r_i)]\)中最大的,求 ...