暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

什么是RabbitMQ?

一杯咸茶 2022-02-21
1382
争取努力一文将RabbitMQ讲清楚。
注:本文将继续沿用自问自答的形式,一步步揭示各类软件从业者在工作中遇到的工具。
目录思维导图:

1.什么是RabbitMQ?

答案:首先要介绍RabbitMQ之前,我们有必要介绍一下MQ,MQ是什么呢?
MQ的全称是Message Queue, 字面意思:“消息队列”。“消息队列”是在消息的传输过程中保存消息的容器,简单来说就是消息(数据)以“管道”的形式在两个应用之间传递。
知道了MQ,那么我们大致也能猜到RabbitMQ是什么了:一种消息代理或队列的管理器(软件),简单地说:它是定义消息队列的软件,应用程序连接到队列以传输一条或多条消息。
消息可以包含任何类型的信息。例如,它可能包含有关在一个应用程序上(亦或是服务器上)启动的进程或任务的信息、或者它可能只是一条简单的文本字符串消息,也可能是包含嵌入对象的内容。 队列管理器软件存储消息,直到接收应用程序连接并从队列中取出消息。接收应用然后处理该消息。
好,我们现在知道什么是RabbitMQ了,那么查阅资料,并根据以上描述做个总结:
RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在不同应用之间共享数据(跨平台跨语言)。RabbitMQ是基于AMQP协议,使用Erlang语言编写实现;同时还支持XMPP、SMTP、STOMP等协议。
      根据上述的介绍,我们发现RabbitMQ是基于AMQP协议实现的,那么心里不免又多出了下面这个疑问。
2. 什么是AMQP?
答案:AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦和通讯。(关于什么是中间件,以后会另作文章介绍,这里不作深入。)
AMQP的主要特征是面向消息、队列、路由(包括“点对点”和“发布/订阅”)、可靠性、安全。
从上述的描述我们知道,AMQP是个“开放“的标准协议;这从根本上避免了生产厂商的封闭,使用任何语言的各种客户都可从中受益。这种协议提供了相当复杂的消息传输模式,所以基本上不需要MassTransit或NServiceBus的配合。同时它还具有”企业级“的适应性和稳定性。
上述描述中有两个词引起了我的好奇:”点对点“和”发布/订阅“,根据查阅解释如下
3.什么是”点对点“和“发布/订阅”?
答案:经查,这两位大佬是JMS当中的两种消息模型;这个时候,我的脑瓜子又在刨根问底地蹦出一个问题:啥又是JMS呢?
JMS(JAVA  Message Service)是java的消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输。JMS API是一个消息服务的标准,或者说是规范;它允许应用程序组件基于JavaEE平台创建、发送、接收和读取消息。使得分布式通信耦合度更低,消息服务更加可靠以及异步性。ActiveMQ就是基于JMS规范实现的。
JMS两种消息模型
  • 点到点(P2P)模型
    队列(Queue)作为消息通信的载体;满足生产者与消费者模式,一条消息只能被一个消费者使用,未被消费的消息在队列中保留到被消费或超时。比如:我们生产者发送100条消息的话,两个消费者来消费一般情况下两个消费者会按照消息发送的顺序各自消费一半(也就是你一个我一个的的消费)
  • 发布/订阅(Pub/Sub)模型
    话题(Topic)作为消息通信载体,类似于广播模式;发布者发布一条消息,该消息通过话题传递给所有订阅者,在一条消息被广播出去之后,刚刚才订阅的用户则是收不到该消息的。
现在我们解决了在介绍RabbitMQ过程中,遇到的不熟悉概念;那么继续接着介绍RabbitMQ
4.为什么我们要用RabbitMQ以及什么时机下使用它呢?
答案:首先我们来说理由,为啥咱们费尽心思要了解这个玩意呢。给出以下10条无法抗拒的理由:
  1. 解耦
    在项目启动刚开始时候,让开发人员预测将来项目会碰到什么需求。那基本上是让这位可怜的开发人员原地自爆,是极其困难的。举个栗子:假设有系统B、C、D都需要A系统的数据,传统的做法就是写三个方法指向到B、C、D系统;有消息时,调用这三个方法将数据发送至各自系统。这个时候需求变了,D系统被“炮”轰掉了,以后没有这个系统了。那系统A就会把跟D系统关联的代码删掉。但此时又有个新系统E需要A的数据,那么就又得重新更改A系统的代码;是不是感觉陷入一个怪圈很烦,很让人恼火。机智的开发人员这时就想到:为降低这种强耦合,使用MQ,系统A只需要把消息(数据)发送到MQ,其他系统有需要,自己连接到MQ,自己“拿”这个消息即可。
  2. 冗余
    有时候,在处理数据的时候会出现意外而导致失败;除非数据被持久化,否则将永远丢失,木有了,再也找不到了;哈哈哈哈,不皮了,接着讲;
    首先消息队列会把数据先进行持久化,直到消息被完全处理,通过这一持久化的方式规避了数据丢失的风险。在许多消息队列所采用的这种“插入-获取-删除”范式中,把一个消息从队列删除之前,需要你的处理过程明确的指出该消息已经被处理完毕,确保你的数据被安全的保存直到你使用完毕。
  3. 扩展性
    因为消息队列解耦了你的处理过程,所以消息的入队速率和处理的频率可以被动态的扩大是很容易的;只需增加处理过程即可。不需改变代码、不需要调节参数。扩展性就像是夏日开调低空调温度一样简单。
  4. 灵活性 & 峰值处理能力
    举个栗子:双11购物节时候,你的女朋友们为购买GTX3090奋力厮杀时候,导致淘宝的访问流量飙升到一个非比寻常的恐怖水平;亦或是明星”造瓜“时,各路瓜友纷纷访问微博一样。在访问量激增的情况下,淘宝和微博仍需继续发挥”坚挺“的作用,但这种突发流量并不常见;如果为以能处理这类峰值访问投入大量资源并随时待命,那无疑是软妹币在流失啊,浪费啊。
    使用消息队列可以解决以上”忧愁“,能够使关键组件顶住增长的访问压力,而不是因为超出负荷的请求而完全崩溃。
    假设此时此刻淘宝有5000个大妹子,同一时间为了你抢最新的RTX3090;如果没有MQ,那么这一瞬间的访问量对数据库来说处理不过来,导致MYSQL崩溃了,系统瘫痪; 如果使用MQ,不再是直接发送查询请求到数据库,而是把数据发送到MQ,MQ短时间积压数据是可以接受的,然后由下游消费者每次拉取2000条进行处理,防止在请求峰值时期大量的请求直接发送到MySQL导致系统崩溃。
  5. 可恢复性
    当系统正常运行中,MQ下游的处理消息的进程挂掉了,并不会影响整个系统。消息队列降低了进程间的耦合度,所以处理进程挂了几个,之前加入队列的消息仍可以在系统恢复后继续被处理。这种允许重试和延后处理请求的能力通常只会影响一两个倒霉蛋儿用户,并不会造成系统整体性灾难。
  6. 送达保证
    消息队列提供的荣誉机制保证了消息能切实的被处理,只要一个进程读取了该队列即可。在此基础之上,提供了一个”只送达一次“的保证。无论有多少进程在接收侧领取数据,每个消息只能被处理一次。这个方式之所以能成为可能,那是因为获取一个消息只是”预定“了这个消息,暂时把它移出了队列。除非客户端明确的表示已经处理完了这个消息,否则这个消息会被放回到队列当中去,在一段可配置的时间之后可再次被处理。
  7. 排序保证
    在多数场景下,数据处理的顺序极其重要。消息队列本来就是排序的,并且能保证数据会按特定的顺序来处理。IronMQ保证消息将会通过FIFO(先进先出)的顺序来处理,因此消息在队列中的位置就是从队列中检索他们的位置。
  8. 缓冲
    在所有在运行的系统中,可以想到肯定存在不同处理时间的元素。譬如,加载一张动图比应用条件过滤器花费更少的时间。
    消息队列通过一个缓冲层帮助任务以最高效率来执行--写入队列的处理会尽可能的快速,而不受从队列读取的预备处理的约束。该缓冲有助于控制和优化数据流经过系统的速度
  9. 理解数据流
    在分布式系统中,如果从用户的一个操作会用多长时间及其系统表现总体印象(耗时以及系统响应速度),我们无从得知,或者说很难得到靠谱的数据表征;但是基于消息队列,通过消息被处理的频率,来方便辅助确定那些表现不佳的处理过程或者领域模型,这些地方的数据流都不够优化。
  10. 异步通信
    在系统的很多情况下,并不希望系统立即处理消息,给用户以实时的反馈。那么消息队列提供了异步处理机制,允许你把一个消息放入队列,但并不立即处理它。譬如用户下单后的,货物分配问题。可以向队列中放入多少消息就放多少,然后在系统闲暇时,进行核账对库存等操作处理。
    基于以上原因,使用消息队列在进程或应用之间进行通信成了最好的形式
            要了解一样东西,我们不能仅仅只知道它的概念和用途,应该继续深入挖掘和了解。譬如,用它时候,明它的使用场景,特点、原理、构造等等。
5.请问RabbitMQ有哪些特点?
答案:依据官网的描述,总结为以下几点:
  • 可靠性。支持持久化,传输确认,发布确认等保证了MQ的可靠性
  • 灵活的分发消息策略。这是RabbitMQ的一大特点。在消息进入MQ前由Exchange(交换机)进行路由消息。分发消息策略有:简单模式,工作队列模式、发布订阅模式,路由模式、通配符模式
  • 支持集群。多台RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker
  • 多种协议。RabbitMQ支持多种消息队列协议,比如STOMP、MQTT等等
  • 支持多种语言客户端。RabbitMQ几乎支持所有常用编程语言,包括JAVA、.NET、Ruby等等
  • 可视化管理界面。RabbitMQ提供了一个简单易用的用户界面,使得用户可以监控和管理消息Broker
  • 插件机制。RabbitMQ提供了很多插件,可以通过插件进行拓展,也可以编写自己的插件
6.请问Rabbit中的组成部分有哪些?
答案:首先我们来看一张架构图
这其中包含了RabbitMQ大多数概念
  • Producer:消息的生产者;生产方客户端将消息同交换机路由发送到队列中
  • Broker:表示消息队列服务器实体(rabbitmq-server)
  • v-hostVirtual Host虚拟主机。标识一批交换机、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个vhost本质上就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换机,绑定和权限机制。vhost是AMQP概念的基础,必须在链接时指定,RabbitMQ默认的vhost是/ ;
    一个Broker中可以设置多个virtual Host,用作不同用户的权限隔离
  • Exchange:交换器用来接收生产者发送的消息并将这些消息路由给服务器中的队列
  • Queue:消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将消息取走
  • Binding:绑定,用于消息队列(Queue)和交换机(Exchange)之间的关联(虚拟连接)。一个绑定就是基于路由键将交换机和消息队列链接起来的路由规则,所以可以将交换机理解成一个由绑定构成的路由表。Binding中可以包括多个Routing Key(路由键)
  • Channel:信道,多路复用连接中一条独立的双向数据交流道。信道是建立在真实的TCP连接内地虚拟连接,AMQP命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成的。因为对于操作系统来讲,建立和销毁TCP都是非常昂贵的的开销,所以引入了信道的概念,以复用一条TCP连接,
  • Connection:应用程序与Broker之间的网络连接,比如一个TCP连接
  • Consuer:消息的消费者(接收消息的程序或进程)
  • Routing Key:路由规则,虚拟机通过它来确认如何路由一个特定的消息
在第五个问题中,我们提到灵活的五种分发策略,问题9中就来详细介绍分发策略
7.请介绍RabbitMQ消息流是怎样的?
答案:首先在介绍消息流之前,我们来通过一个例子来了解整个消息传输过程;
假设有这么一个场景:用户将信息上传到网站的场景,站点处理此消息,生成PDF,并将其通过电子邮件发送给客户。当用户在Web界面输入用户信息时,Web应用程序将创建一条“PDF”待处理“消息”,其中包含用户需要的所有重要信息,并将其放入RabbitMQ中定义的队列中。(在本例子中,处理信息、生产PDF和发送电子邮件将需要几秒钟。这就是为什么使用消息队列的原因之一)
  1. 用户向Web应用程序发送PDF创建请求
  2. Web应用程序(生产者)向RabbitMQ发送一条消息,其中包含来自请求的数据,例如姓名和电子邮件
  3. 交换机接受来自生产者的消息并将它们路由到正确的消息队列以创建PDF
  4. PDF处理工作者(消费者)收到任务消息并开始处理PDF

通过上述过程,我们可以清晰地发现消息并不是直接发布到队列中;相反,生产者将消息发送到交换器。交换器负责在绑定和路由键的帮助下将消息路由到不同的队列。绑定是队列和交换器之间的连接
RabbitMQ中的消息流:
  1. 生产者向交交换器发布消息。创建交换时,必须指定类型(下个问题将揭晓多种类型)
  2. 交换机收到消息,现在负责路由消息。交换机会根据交换类型考虑不同的消息属性,例如路由密钥
  3. 绑定必须从交换机创建到队列。上图中,有两个绑定到来自交换机的不同两个队列。交换机根据消息属性将消息路由到队列中
  4. 消息保留在队列中,直到被消费者处理
  5. 消费者处理消息
8.交换机的四种类型都是什么?
答案:在上述问题中,我们知道了交换器的作用:被用来接收生产者发送的消息,并将这些消息路由给服务器中的队列。那么我们知道交换机是什么吗?貌似还是一脑子懵圈状态;那么我们查一下官方文档,在发布订阅中有作解释:
RabbitMQ消息传递模型中的核心思想是生产者从不将任何消息直接发送到队列。实际上,生产者经常甚至根本不知道是否将消息传递到任何队列。相反,生产者只能将消息发送到交换机。交流是一件非常简单的事。一方面,它接收来自生产者的消息,另一方面,将它们推入队列。交换机必须确切知道如何处理收到的消息。是否应将其附加到特定队列?是否应该将其附加到更多队列中?还是应该丢弃它。规则由交换机类型定义。
据此我们知道了RabbitMQ中交换机的概念,交换机负责借助标头属性、绑定和路由键将消息路由到不同的队列
绑定:设置用于将队列绑定到交换的“连接”
路由键:交换机在决定如何将消息路由到队列时查看的消息属性(取决于交换器类型)
交换机、连接和队列可以使用持久、临时和创建时自动删除等参数进行配置。持久交换在服务器重启后仍然存在,并持续到它们被明确删除。在RabbitMQ关闭之前存在临时交换。一旦最后一个绑定对象从交换中解除绑定,自动删除的交换就会被删除。
在RabbitMQ中,有四种不同类型的交换,它们使用不同的参数和绑定设置以不同的方式路由消息。客户端可以创建自己的交换或使用服务器首次启动时创建的预定义默认交换。
四种类型:
  • Direct(直接交换机):消息被路由到绑定键与消息的路由键完全匹配的队列。例如,如果队列使用绑定键pdfprocess绑定到交换器,则使用路由键pdfprocess发布到交换器的消息将被路由到该队列

  • Fanout(扇形交换机):不处理routekey,直接把消息路由到绑定到它的所有队列中

  • Topic(话题交换机):在“路由键”和“绑定中指定的路由模式”之间进行通配符匹配;根据routeKey把消息转发到符合规则的队列中,其中#用于匹配符合一个或者多个词(范围更广),*用于匹配一个词。

  • Headers(头部交换机):交换机使用消息标头属性进行路由;根据消息的headers路由转发消息,而不是通过路由键,其中header是一个Map,也就意味着不仅可以匹配字符串类型,也可以匹配其他类型数据。规则可以分为所有键值对匹配或单一键值对匹配

9.RabbitMQ7种分发消息策略(消息模式)都是哪些?
答案:Rabbit总共提供了7种消息模型;其中6和7有些特殊;
6:RPC是发布者发布消息,并通过RPC(远程调用)方式等待结果。应用场景少,代码复杂,不做介绍。
7:Publisher Confirms是消息确认机制。指的是生产者如何发送可靠消息,并非消息队列,同样不多做介绍。

剩下的5种模式:
  • Simple Work Queue(简单工作队列模式):也就是常说的点对点模式,一条消息由一个消费者进行消费。(当由多个消费者时,默认使用轮询机制把消息分配给消费者)

  • Work Queues(工作队列模式):也叫公平队列,能者多劳的消息队列模型。队列必须接收来自消费者的手动ack才可以继续往消费者发送消息。

  • Publish/Subscribe(发布订阅模式):一条消息被多个消费者消费.


  • Routing(路由模式):有选择的接收消息

  • Topic(主题模式):通过一定的规则来选择性的接收消息

到此我们学习了多种交际类型和消息模式。那它们之间有没有什么关联或者联系呢?

我们通过下面这张表格,来揭示两者间的关系

消息模式交换机类型
Simple Work Queue(简单工作队列),Work Queues(工作队列)
空交换机
Publish/Suscribe(发布订阅模式)

fanout(扇形交换机)

Routing(路由模式)direct(直接交换机)
Topics(主题模式)
topic(主题交换机)

关于上述五种消息队列模式的编码参考内容请阅览官方文档,这里不做赘述。

上一篇Linux及Docker网络基础知识

下一篇:事件总线一窥


文章转载自一杯咸茶,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论