RabbitMQ 基础概念的理解

                             预计阅读时间:12分钟

本文文字虽多,字字浓缩,静下心来,学习需要沉淀。

目录直通车

一、程序中为什么要用MQTT?

二、MQTT是什么?

1、Qos(确保消息送达)

2、LWT(临终遗嘱)

三、关于RabbitMQ

1、拍RabbitMQ的“马屁”

(1)自带“光环”

(2)是实现了AMQP标准的消息服务器

(3)RabbitMQ支持持久化

(4)集群部署简单

(5)社区活跃度高

2、什么是AMQP?

3、RabbitMQ的工作流程

(1)基本概念

(2)工作流程分析

(3)消息发送原理:


一、程序中为什么要用MQTT?

本文大部分偏向于程序设计部分的内容。

基础与原理是非常重要的。在学习 RabbitMQ 之前,先了解一下 MQTT协议。其实你也发现了都是为了解决什么问题才出现一项新技术的。

那么在程序中应用MQTT是为了解决什么问题?简单来说就是“削峰填谷”。举个栗子吧~

在以前,比如说我们秒杀抢购商品的时候,用户量在某个时间段暴增,达到峰值之后,服务器宕机,页面直接卡死报个错给用户,这样的用户体验是极差的,比如说某些学校的选课系统。为什么会发生这样的情况?页面的数据来源于数据库,当用户量在某个时间暴增的时候,此时程序不断的查询、新增,一般的数据库是承受不了这样么大的“压力”的,就会把数据库服务器直接搞宕机了。使用了消息队列机制之后,在用户秒杀抢购商品的时候,系统会提醒我们稍等排队中,而不是以前那样页面卡死或报错给用户,程序就将队列一个一个处理,就不会出现卡死的情况了。

二、MQTT是什么?

现在网上回答这个问题的文章很多,我就简单的总结后浓缩成了一句话:MQTT(Message Queuing Telemetry Transport Protocol)是基于TCP/IP 栈构建的轻量级、灵活消息队列遥测传输协议。

看完之后其实发现啥用都没有,也理解不了。管它那么多,就记住这是基于 TCP/IP 协议的创建的协议。

MQTT有两个非常重要的概念,一个是Qos(确保消息送达),另一个LWT(临终遗嘱),请看下面表格:

1、Qos(确保消息送达)

Qos

状态描述

0

协议对此等级应用信息不要求回应确认,也没有重发机制,这类信息可能会发生消息丢失或重复,取决于TCP/IP提供的尽最大努力交互的数据包服务。

1(最少发送一次)

确保信息到达,但消息重复可能发生,发送者如果在指定时间内没有收到发布确认(PUBACK)控制报文,应用信息会被重新发送。

2(只发送一次)

最高级别的服务质量,消息丢失和重复都是不可接受的。

2、LWT(临终遗嘱)

说白了就是死前做的一件事。比如说,当客户机断开时,代理服务器就会采取相应的措施,客户端设置完成LWT之后,当代理服务器检测到客户端离线后,就会发送保存在特定主题上的 LWT 信息,让其它订阅该主题的客户端知道该节点已经意外离线。这个是MQTT利用KeepAlive机制

三、关于RabbitMQ

到此大家定有所疑惑,如我刚学时亦是如此。为什么要用这个玩意儿,基于MQTT开发的MQTT服务器只有只一个吗?它的运作模式是怎样的?先提三个问题在这里。

1、拍RabbitMQ的“马屁”

(1)自带“光环”

Rabbit MQ 是 Erlang语言开发的。Erlang是一种面向并发运行环境的通用编程语言意思就是说天生自带高并发和高可用光环)。

(2)是实现了AMQP标准的消息服务器

现在市面上有如ActiveMQ、ZeroMQ、Appche Qpid等MQTT服务器,Qpid也挺不错的同样开源,为何指名点姓要RabbitMQ。

上面讲到实现了AMQP协议的MQTT服务器只有Qpid和RabbitMQ。我简单说一个理由,Qpid的社区不够活跃,不服请看下图:

RabbitMQ 基础概念的理解

RabbitMQ 基础概念的理解

(3)RabbitMQ支持持久化

保证了消息的稳定性。注意:持久化也是有缺点的,写入硬盘比写入内存性能低很多,从而降低了服务器的吞吐量,尽管使用SSD硬盘可以使事情得到缓解,但他仍然吸干了Rabbit的性能,当消息成千上万条要写入磁盘的时候,性能是很低的。所以使用者要根据自己的情况来选择。

(4)集群部署简单

不仅因为Erlang,还支持Docker。

(5)社区活跃度高

2、什么是AMQP?

这里不做重点,浓缩了以下内容:

Advanced Message Queuing Protocol,高级消息队列协议。说白了就是一个进程间传递异步消息(异步就是将消息发送给接收方时,接收方不用等待接收完成)的网络协议。

既然说到这里了,在说下同步传输,数据没有被对方确认收到则调用传输的函数就不返回,举个例子吧:你现在传输,我要亲眼看你传输完成,才去做别的事

先来看下下面这张AMQP的模型图,在看工作过程。

RabbitMQ 基础概念的理解

发布者(Publisher)发布消息(Message),经由交换机(Exchange),交换机根据路由规则(由交换机类型和绑定(Bindings)规则)将收到的消息分发给与该交换机绑定的队列(Queue),最后 AMQP 代理(Broker)会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取。

交换机可以有两个状态:持久化(durable)、暂存(transient)。交换机是有多种的

持久化的交换机会在消息代理(broker)重启后依旧存在,而暂存的交换机则不会(它们需要在代理再次上线后重新被声明)。

注意:并不是所有的应用场景都需要持久化的交换机。

3、RabbitMQ的工作流程

零基础的朋友先看基本概念!

(1)基本概念

生产者(Producer):消息的创建者,负责创建和推送数据到消息服务器;

消费者(Consumer):消息的接收方,用于处理数据和确认消息;

代理(Broker):即RabbitMQ,人送外号“快递员”。

 

(2)工作流程分析

“粗”理解

RabbitMQ 基础概念的理解

这个图其实自己细看还是能看懂的,只是对英文有种恐惧感吧~

这里有个Create PDF的请求发送给生产者,生产者响应请求之后把消息传递到 RabbitMQ(代理机) 里面去,这里的CloudAMQP 是官方为了突出支持AMQP 标准,可以异步响应消息,不用太在意。消息首先是传递到RabbitMQ内部的交换器,然后交换器根据约定好的路由规则或算法分到队列里面去,从RabbitMQ出来之后,消息才传递给订阅了该主题的用户。

“细”理解

生产者将消息发送给代理机的细节:

下图有三类交换机:

1、Diredct,通过key绑定,只有key相同的队列才会收到消息。

2、Topic,类似正则,按照不同的模式匹配"#" 表示一个或多个单词,"*" 仅匹配一个。

3、Fanout,即广播方式,exchange把接收到的消息发给所有绑定的队列。

RabbitMQ 基础概念的理解

交换器绑定多个队列的细节:

RabbitMQ 基础概念的理解

(3)消息发送原理:

有一个误区:可能会想到我之前强调过MQTT是基于TCP/IP构建的,这里应该是通过TCP来传递消息。

实际上是通过信道(Channel)来传递消息(Message)的。对于操作系统来说,创建和销毁TCP会话是很贵的!比如说,我在文头举的例子,倘若高峰期有一千万的用户量,创建一千个TCP会话,这些会话对于系统来说,销不销毁都很贵,而且TCP会话是有限的。

所以在创建的一条TCP里使用信道来传输消息是十分可取的,如下图所示:

RabbitMQ 基础概念的理解

通过TCP连接RabbitMQ Server,Server端会给连接并认证成功的Client创建一条AMQP信道。

信道是创建在“真实”TCP上的虚拟连接,AMQP命令都是通过信道发送出去的,每个信道都会有一个唯一的ID,不论是发布消息,订阅队列或者介绍消息都是通过信道完成的。