RabbitMQ

前言

很早就想要学习一种MQ了,RabbitMQ是一个很好的切入点
如果有些知识点认识错误,欢迎指出。

系列

同步异步(wx.request+ajax)
消息队列的学习与理解
消息队列之RabbitMQ的学习
RabbitMQ的应用之spring-boot-starter-amqp

选型

关于MQ中间件的选型,一直在纠结,即使早已撇开重量级的kafka以及轻量级的ActiveMQ,Rocket和RabbitMQ两者的选择都让我花费了好长的时间。从各种网站进行搜索两者的区别,一个又一个参数收入眼中,但还是没有什么概念。也许 技术选型 也是需要功力的。

但是慢慢地觉得,为何纠结呢,即使再有区别,在小项目的面前,并不会有什么体现的。

最重要的是关于两者的实现以及内核,才是我需要思考的。

时间线

2020.09.12-2020.09.13—完成初稿

参考链接

文档

RabbitMQ文档

https://www.rabbitmq.com/

RabbitMQ中文文档

http://rabbitmq.mr-ping.com/

http://rabbitmq.mr-ping.com/AMQP/AMQP_0-9-1_Model_Explained.html

RabbitMQ学习

https://www.cnblogs.com/wutianqi/p/10043011.html

关于RabbitMQ的问题的解决方案

定义:AMQP与RabbitMQ

学习RabbitMQ一直都有AMQP的身影,之前以为AMQP只是实现RabbitMQ的一种协议。学习之后才知道,原来两者的关系是同等的,有联系但并不是谁依赖谁。脱离开对方,还有其它的用途与实现方式。

当我们使用RabbitMQ时,其实是在使用AMQP协议,RabbitMQ只是其中的一部分。

AMQP

AMQP即(Advanced Message Queue Protocol 高级消息队列协议):是一种网络协议,它支持符合条件的客户端和消息代理中间件进行通讯。

RabbitMQ

RabbitMQ是一个轻量级的消息代理中间件支持多种协议,其中最为重要的是AMQP

AMQP的概念同样符合RabbitMQ

AMQP和RabbitMQ

从上面就可以知道,其实AMQP和RabbitMQ有联系但并不是谁依赖谁

AMQP支持各种信息交换的体系结构

存储转发,分布式事务,发布订阅,基于内容的路由,文件传输队列,点对点连接

其中发布订阅的一种实现就是RabbitMQ

RabbitMQ支持多种协议

官方文档描述:https://www.rabbitmq.com/protocols.html

AMQP 0-9-1和扩展协议, STOMP,MQTT,AMQP1.0,HTTP

但是RabbitMQ是通过插件机制支持AMQP之外的协议

特点

异步消息技术(支持多种消息协议,消息投递确认机制,多种交换器,灵活的消息路由)

支持多客户端语言

分布式集群部署

支持运行于多种操作系统

内置强大的服务器监控系统

AMQP

AMQP模型

在这里插入图片描述

组件
生产者(发送)

生产者顾名思义,就是生产消息的角色,生产者会将消息发送给交换机。

为了使交换机将正确地将消息发送给对队列,发送消息时需指定消息地路由键(routing key);

消息代理Broker(接收+发送)

Broker消息代理,这里指的是就是RabbitMQ,负责接收发布者发布的消息,并将消息推送给订阅了消息的消费者。

虚拟机Virtual Host

当多用户使用同一个RabbitMQ Server时,可以划分出多个vhost,并被用户使用。类似于一台计算机,有多用户。

交换机Exchange

交换机拿到一个消息之后,将它路由给一个或零个队列。使用哪种路由算法时有交换机类型bingings的规则,即路由键所决定的。

路由键routing key

交换机与队列之间的绑定规则。

绑定Binding

交换机和队列之间通过路由键routing key 相互绑定起来。

消息队列Message Queue

消息的载体,消息将在这里等待消费者取走或推送给消费者。

Connection

生产者和消费者与消息代理之间的连接

通道Channel

每一次在消息代理与消费者之间建立连接的话,将会有巨大开销。

而Channel是Connection内部建立的逻辑连接,且相互隔离的,可以极大减少操作系统建立TCP Connection的开销。

消费者

接收消息的角色就是消费者

分析
正常情况下

生产者(publisher)生产具有指定路由键的信息将其发送到**消息代理Broker(RabbitMQ Server)中的交换机(Exchange);

交换机将收到的消息根据路由规则分发给绑定的队列(Message Queue);

最后Broker会通过连接中的通道(Channel)投递订阅了消息的消费者。

异常

从安全角度考虑,网络是不可靠的,所以处理消息的过程中会出现异常。

消息确认

基于此原因,AMQP模块包含了一个消息确认的概念

当一个消息从队列中投递给消费者后,消费者会通知以下消息代理。

这个机制可以是自动的,也可以是手动的(由开发者进行处理)。

当消息确认被启用时,消息代理不会完全将消息从队列中删除,直到收到来自消费者的确认回执。

与笔记“消息队列”中描述的邮局模型一致。

死信队列

在某些情况下,当一个消息无法被成功路由时,消息或许会被返回给发布者并被丢失。

或者,消息代理执行了延期操作,消息会被放入死信队列

消息发布者可以选择某些参数来处理这些特殊情况。

处理机

处理机类型

处理器类型主要有4种——直连交换机,扇形交换机,主题交换机,头交换机,还有1种默认交换机。

默认交换机default exchange

实际上是由消息代理预先声明好的直连交换机

每个新建队列都会自动绑定到默认的交换机上,绑定的路由键名称与队列名称相同。如下:

在这里插入图片描述

换句话说,默认交换机看起来貌似能够直接将消息投递给队列,尽管技术上并没有做相关的操作

直连交换机direct exchange

根据消息携带的路由键将消息投递给对应队列。直连交换机用来处理消息的单播路由(也可以处理多播路由);

所以直连交换机更像是一对一交换机.

在这里插入图片描述

工作流程

将一个队列绑定到某个交换机上,同时赋予该绑定一个路由键.

当一个携带路由键为R的消息被发送到直连交换机时,交换机会把它路由给routing key为R的队列.

注意:直连交换经常通过循环分发的方式发送消息,所以消息的负载均衡是发生在消费者之间,而不是队列之间.


扇形交换机fanout exchange

扇形交换机会将消息路由到所有与之绑定的队列,而不理会路由键,所以扇形交换机,也称为广播交换机.

在这里插入图片描述

应用案例
  • 大规模多用户在线游戏使用它来处理排行榜更新等全局事件,注意是实时
  • 体育新闻网站使用它近乎实时将比分更新分发给移动客户端
  • 广播各种状态和配置更新
主题交换机

主题交换机通常用户实现消息的多播路由,只要消息的路由键符合交换机与队列之间的路由键模式,就会将消息路由到该队列.

其中主题是有路由键的模式决定的.

在这里插入图片描述

规则

其实这些规则有点像是正则表达式的镜像,有以下几点:

  1. 使用.分隔单词
  2. 一个单词使用*
  3. 0个或多个单词使用#

根据以上规则,有以下例子:

*.zhj.*
# 可以匹配以下内容
pro.zhj.check	check.zhj.image	# 使用*表示1个字符
#.zhj.*
# 可以匹配以下内容
zhj.pro.check	# 使用#表示0个字符
zhj.check.zhj.image	# 使用#表示多个字符
应用案例

其实 主题就代表分类,所以分类新闻之类的模块都是使用主题交换机.

头交换机(header exchange)

头交换机的头指的是消息头。头交换机会使用多个匹配的header与队列绑定.消息从生产者处发送到交换机时,会将消息的消息头与交换机与队列绑定的消息头进行匹配,符合的话,就会将该条消息发送给符合的队列.

在这里插入图片描述

规则

消息头可以是整数,也可以是一个字典.当消息头是一个字典时:

message_header = {
    'x-match':any,
    ...
}
# 以上消息头 只要message_header中的一条属性值匹配,即符合
message_header = {
    'x-match':all,
    ...
}
# 以上消息头 必须message_header中的所有属性值匹配,才符合
总结

AMQP0-9协议一共有4种交换机类型,另外还有一种默认交换机。

直连交换机,扇形交换机,主题交换机,头交换机

前三种是根据路由键routing key与队列相互绑定的,而最后一种头交换机是通过消息头绑定的。

交换机的职责非常简单,就是根据绑定的规则,将消息发送到队列中。

处理机属性

名字Name

交换机名称。

持久性Durability

交换机有持久(durable)和暂存(transient)两个状态。

区别在于消息代理重启后,交换机是否存在。

持久表示消息代理重启后,交换机还是存在的。而暂存则相反,需要消息代理上线后重新定义。

自动删除Auto-delete

当所有与之绑定的消息队列都完成了对此交换机的使用后,删掉它。

Arguments依赖代理本身

队列

AMQP中的队列和其它消息队列一样,存储着即将被应用消费的消息。

属性
Name
Durable

同交换机一样的概念,消息代理重启后,队列是否存在

Exclusive

只被一个连接使用,当连接关闭后,队列即将被删除

Auto-delete

当最后一个消费者退订后即被删除

Arguments
名称

队列的名称可以由应用来取,也可以让消息代理自动生成。

持久化

持久化队列会被存储在磁盘上,当消息代理重启时,依旧存在;暂存队列则相反。

另外,持久化队列的持久性只是对于队列而言,所以持久化队列处理的消息如果没有持久化的话,

该消息也是不能重新恢复的。

绑定

绑定是一个名词,指的是交换机与队列之间的绑定。

常常绑定会与路由键一起出现,因为消息是根据路由键路由到某个队列的。

生产者

生产者是指消息的生产者。消息从生产者生成后,发送给消息代理,即RabbitMQ。

动作:推送消息
动作:消息确认

生产者推送消息到Rabbit Server的消息确认有4种情况,分别是:

  • 找不到交换机
  • 找到了交换机,但是找不到队列
  • 交换机和队列都找不到
  • 推送成功

总结:其实就是2个对象交换机和队列,2种状态找到与找不到两两组合。

消费者

消息的意义在于被应用消费。而消费者就是实现者。

动作:推和拉

为了达到此目的,有两种方式:

  • 队列将消息投递给应用
  • 应用根据需要主动获取消息

从上面的两种方式,可以有以下画面:

在这里插入图片描述

区别
  • 动作的发起者不同

    动作推的发起者是队列,队列将消息推给消费者;

    动作拉的发起者是消费者,消费者从队列拉取消息

网络是不可靠的,因为不知道处理消息的过程中会发生什么?网络中断,服务宕机都有可能会发生。

所以需要一些动作来确保消息能够被正常处理。

动作:消息确认

消息的确认影响着AMQP的消息代理什么时候删除消息。有2种解决方案。

  • 自动确认模式:当消息代理将消息发送给应用后立即删除消息

  • 手动确认模式:待应用发送一个确认回执后删除消息
    在这里插入图片描述

注意:手动确认模式中应用发送确认回执并不是说收到消息后,而是由应用自己决定。

即应用可以在收到消息后立即发送,或者将未处理的消息存储后发送,亦或者等到消息被处理完毕后再发送,共3种情况下发送确认回执。

这里涉及2个动作——消息代理删除消息,消费者发送确认回执

当然,这些的前提是消费者没有挂掉。

当消费者挂掉之后,即消息代理与消费者的连接中断,消息代理会知道这一状况,

并会把消息重新发送给另一个符合要求的消费者。

如果没有符合的消费者,消息代理会死等下一个符合要求的消费者,再进行发送。

这一切,源于消息代理的一个机制——当开启确认回执功能后,消息代理尚未得到确认回执,消息代理会重新发送一遍。


动作:拒绝消息

如果拒绝消息,消费者应该向消息代理表明——本条消息由于“拒绝消息”的原因处理失败。

并且告诉消息代理如何处理该条消息——销毁或者重新放入队列。

如果当前只有一个符合但不适合的消费者,不可选择重新放入队列,因为会造成死循环。

消息代理发过去,消费者收到但不想/不适合处理,又发回给消息代理。无限死循环。


消息

其实说了那么多,有一个非常重要的对象也是需要说一说的——消息

消息由生产者生成,发送到交换机,交换机再将其路由到某个队列。

队列再将其发送给消费者。可以说消息串联起了整个工作流程

属性
内容类型Content type
内容编码Content encoding
路由键Routing key

投递模式Delivery mode

即前面所说的持久还是暂存

消息能够以持久化的方式发布,其持久化在磁盘上。

消息的持久性完全取决于自身,处理机和队列的持久性不会影响消息的持久性。


消息优先权Message priority
消息发布的时间戳Message publishing timestamp
消息有效期Expiration period
发布者ID—Publisher application id
消息头headers

消息属性需要在消息被发布的时候定义

消息确认

AMQP模型有两个消息确认,分别是生产者推送消息确认,以及消费者接收消息后的消息确认

思维导图

在这里插入图片描述在这里插入图片描述在这里插入图片描述

总结

以上便是全部内容,当然还有许多概念没有讲述完整。等学习到了再进行补充。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐