
1.什么是RabbitMQ?


点到点(P2P)模型 队列(Queue)作为消息通信的载体;满足生产者与消费者模式,一条消息只能被一个消费者使用,未被消费的消息在队列中保留到被消费或超时。比如:我们生产者发送100条消息的话,两个消费者来消费一般情况下两个消费者会按照消息发送的顺序各自消费一半(也就是你一个我一个的的消费) 发布/订阅(Pub/Sub)模型 话题(Topic)作为消息通信载体,类似于广播模式;发布者发布一条消息,该消息通过话题传递给所有订阅者,在一条消息被广播出去之后,刚刚才订阅的用户则是收不到该消息的。
解耦 在项目启动刚开始时候,让开发人员预测将来项目会碰到什么需求。那基本上是让这位可怜的开发人员原地自爆,是极其困难的。举个栗子:假设有系统B、C、D都需要A系统的数据,传统的做法就是写三个方法指向到B、C、D系统;有消息时,调用这三个方法将数据发送至各自系统。这个时候需求变了,D系统被“炮”轰掉了,以后没有这个系统了。那系统A就会把跟D系统关联的代码删掉。但此时又有个新系统E需要A的数据,那么就又得重新更改A系统的代码;是不是感觉陷入一个怪圈很烦,很让人恼火。机智的开发人员这时就想到:为降低这种强耦合,使用MQ,系统A只需要把消息(数据)发送到MQ,其他系统有需要,自己连接到MQ,自己“拿”这个消息即可。 冗余 有时候,在处理数据的时候会出现意外而导致失败;除非数据被持久化,否则将永远丢失,木有了,再也找不到了;哈哈哈哈,不皮了,接着讲; 首先消息队列会把数据先进行持久化,直到消息被完全处理,通过这一持久化的方式规避了数据丢失的风险。在许多消息队列所采用的这种“插入-获取-删除”范式中,把一个消息从队列删除之前,需要你的处理过程明确的指出该消息已经被处理完毕,确保你的数据被安全的保存直到你使用完毕。 扩展性 因为消息队列解耦了你的处理过程,所以消息的入队速率和处理的频率可以被动态的扩大是很容易的;只需增加处理过程即可。不需改变代码、不需要调节参数。扩展性就像是夏日开调低空调温度一样简单。 灵活性 & 峰值处理能力 举个栗子:双11购物节时候,你的女朋友们为购买GTX3090奋力厮杀时候,导致淘宝的访问流量飙升到一个非比寻常的恐怖水平;亦或是明星”造瓜“时,各路瓜友纷纷访问微博一样。在访问量激增的情况下,淘宝和微博仍需继续发挥”坚挺“的作用,但这种突发流量并不常见;如果为以能处理这类峰值访问投入大量资源并随时待命,那无疑是软妹币在流失啊,浪费啊。 使用消息队列可以解决以上”忧愁“,能够使关键组件顶住增长的访问压力,而不是因为超出负荷的请求而完全崩溃。 假设此时此刻淘宝有5000个大妹子,同一时间为了你抢最新的RTX3090;如果没有MQ,那么这一瞬间的访问量对数据库来说处理不过来,导致MYSQL崩溃了,系统瘫痪; 如果使用MQ,不再是直接发送查询请求到数据库,而是把数据发送到MQ,MQ短时间积压数据是可以接受的,然后由下游消费者每次拉取2000条进行处理,防止在请求峰值时期大量的请求直接发送到MySQL导致系统崩溃。 可恢复性 当系统正常运行中,MQ下游的处理消息的进程挂掉了,并不会影响整个系统。消息队列降低了进程间的耦合度,所以处理进程挂了几个,之前加入队列的消息仍可以在系统恢复后继续被处理。这种允许重试和延后处理请求的能力通常只会影响一两个倒霉蛋儿用户,并不会造成系统整体性灾难。 送达保证 消息队列提供的荣誉机制保证了消息能切实的被处理,只要一个进程读取了该队列即可。在此基础之上,提供了一个”只送达一次“的保证。无论有多少进程在接收侧领取数据,每个消息只能被处理一次。这个方式之所以能成为可能,那是因为获取一个消息只是”预定“了这个消息,暂时把它移出了队列。除非客户端明确的表示已经处理完了这个消息,否则这个消息会被放回到队列当中去,在一段可配置的时间之后可再次被处理。 排序保证 在多数场景下,数据处理的顺序极其重要。消息队列本来就是排序的,并且能保证数据会按特定的顺序来处理。IronMQ保证消息将会通过FIFO(先进先出)的顺序来处理,因此消息在队列中的位置就是从队列中检索他们的位置。 缓冲 在所有在运行的系统中,可以想到肯定存在不同处理时间的元素。譬如,加载一张动图比应用条件过滤器花费更少的时间。 消息队列通过一个缓冲层帮助任务以最高效率来执行--写入队列的处理会尽可能的快速,而不受从队列读取的预备处理的约束。该缓冲有助于控制和优化数据流经过系统的速度 理解数据流 在分布式系统中,如果从用户的一个操作会用多长时间及其系统表现总体印象(耗时以及系统响应速度),我们无从得知,或者说很难得到靠谱的数据表征;但是基于消息队列,通过消息被处理的频率,来方便辅助确定那些表现不佳的处理过程或者领域模型,这些地方的数据流都不够优化。 异步通信 在系统的很多情况下,并不希望系统立即处理消息,给用户以实时的反馈。那么消息队列提供了异步处理机制,允许你把一个消息放入队列,但并不立即处理它。譬如用户下单后的,货物分配问题。可以向队列中放入多少消息就放多少,然后在系统闲暇时,进行核账对库存等操作处理。 
基于以上原因,使用消息队列在进程或应用之间进行通信成了最好的形式 要了解一样东西,我们不能仅仅只知道它的概念和用途,应该继续深入挖掘和了解。譬如,用它时候,明它的使用场景,特点、原理、构造等等。
可靠性。支持持久化,传输确认,发布确认等保证了MQ的可靠性 灵活的分发消息策略。这是RabbitMQ的一大特点。在消息进入MQ前由Exchange(交换机)进行路由消息。分发消息策略有:简单模式,工作队列模式、发布订阅模式,路由模式、通配符模式 支持集群。多台RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker 多种协议。RabbitMQ支持多种消息队列协议,比如STOMP、MQTT等等 支持多种语言客户端。RabbitMQ几乎支持所有常用编程语言,包括JAVA、.NET、Ruby等等 可视化管理界面。RabbitMQ提供了一个简单易用的用户界面,使得用户可以监控和管理消息Broker 插件机制。RabbitMQ提供了很多插件,可以通过插件进行拓展,也可以编写自己的插件

Producer:消息的生产者;生产方客户端将消息同交换机路由发送到队列中 Broker:表示消息队列服务器实体(rabbitmq-server) v-host:Virtual 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:路由规则,虚拟机通过它来确认如何路由一个特定的消息

用户向Web应用程序发送PDF创建请求 Web应用程序(生产者)向RabbitMQ发送一条消息,其中包含来自请求的数据,例如姓名和电子邮件 交换机接受来自生产者的消息并将它们路由到正确的消息队列以创建PDF PDF处理工作者(消费者)收到任务消息并开始处理PDF

生产者向交交换器发布消息。创建交换时,必须指定类型(下个问题将揭晓多种类型) 交换机收到消息,现在负责路由消息。交换机会根据交换类型考虑不同的消息属性,例如路由密钥 绑定必须从交换机创建到队列。上图中,有两个绑定到来自交换机的不同两个队列。交换机根据消息属性将消息路由到队列中 消息保留在队列中,直到被消费者处理 消费者处理消息
RabbitMQ消息传递模型中的核心思想是生产者从不将任何消息直接发送到队列。实际上,生产者经常甚至根本不知道是否将消息传递到任何队列。相反,生产者只能将消息发送到交换机。交流是一件非常简单的事。一方面,它接收来自生产者的消息,另一方面,将它们推入队列。交换机必须确切知道如何处理收到的消息。是否应将其附加到特定队列?是否应该将其附加到更多队列中?还是应该丢弃它。规则由交换机类型定义。

Direct(直接交换机):消息被路由到绑定键与消息的路由键完全匹配的队列。例如,如果队列使用绑定键pdfprocess绑定到交换器,则使用路由键pdfprocess发布到交换器的消息将被路由到该队列 
Fanout(扇形交换机):不处理routekey,直接把消息路由到绑定到它的所有队列中 
Topic(话题交换机):在“路由键”和“绑定中指定的路由模式”之间进行通配符匹配;根据routeKey把消息转发到符合规则的队列中,其中#用于匹配符合一个或者多个词(范围更广),*用于匹配一个词。 
Headers(头部交换机):交换机使用消息标头属性进行路由;根据消息的headers路由转发消息,而不是通过路由键,其中header是一个Map,也就意味着不仅可以匹配字符串类型,也可以匹配其他类型数据。规则可以分为所有键值对匹配或单一键值对匹配 
Simple Work Queue(简单工作队列模式):也就是常说的点对点模式,一条消息由一个消费者进行消费。(当由多个消费者时,默认使用轮询机制把消息分配给消费者)

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

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

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

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

到此我们学习了多种交际类型和消息模式。那它们之间有没有什么关联或者联系呢?
我们通过下面这张表格,来揭示两者间的关系
| 消息模式 | 交换机类型 |
| Simple Work Queue(简单工作队列),Work Queues(工作队列) | 空交换机 |
| Publish/Suscribe(发布订阅模式) | fanout(扇形交换机) |
| Routing(路由模式) | direct(直接交换机) |
| Topics(主题模式) | topic(主题交换机) |
关于上述五种消息队列模式的编码参考内容请阅览官方文档,这里不做赘述。
下一篇:事件总线一窥
文章转载自一杯咸茶,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




