1.什么是协议
提到协议,需要先说一下TCP/IP,网络中的不同个体传输消息,底层可以通过TCP、UDP等机制进行传输。而TCP本身是基于流的传输层协议,并不具备数据描述,数据结构以及数据声明的功能。
但是很多时候,在不同网络个体之间传递数据,需要制定一些规范的数据结构,数据格式。这时候,就需要基于TCP链接,在应用层进行相关数据传输规范的制定,而这种制定的规范,称为协议
(通俗来说,通过一些约定,来从流数据中读取出需要的数据内容,这些约定就是协议)
2.Http协议是否适用于消息中间件
既然协议的制定就是为了数据的传输,那么对于RabbitMq这一类的消息中间件,也必然要遵守一些协议。然而问题就来了,Http协议是否适用于RabbitMq?
理论上来说,可以用,但是不适合
- 首先Http协议的内容太过复杂,请求头和响应头,其中包含了Cookie、请求方式,请求参数,响应状态,响应码等很多内容。然后消息中间件只需要进行消息的发送,消息的持久化以及消息的接收。Http协议对于消息中间件来说,太重了,消息中间件的协议要求就是简洁和高性能
其次,Http协议相对来说是一种短链接,然而消息中间件是需要频繁进行消息的接收和发送,频繁的创建、关闭链接对于追求吞吐量的消息中间件很明显不合适。并且链接关闭很有可能会带来消息数据的丢失,很明显这也是不适合消息中间件的
3.RabbitMq支持的协议
既然Http协议不适合消息中间件,哪些协议又适合呢?接下来,结合RabbitMq支持的协议,对这个问题进行解答
AMQP
AMQP全称Advanced Message Queuing Protocol,翻译为高级消息队列协议。
RabbitMq的默认协议即为AMQP协议起源
在消息中间件这个理念被提出并开始落地商用后,各大厂商都研发了各自的消息中间件。然后一个很大的问题就是,由于每个厂商的中间件协议各不相同,导致用户在使用时,无法做到使用一套协议就可以适配所有消息中间件
2004年 JPMorgan Chase 和 iMatix 公司一起合作开发了AMQP协议,该协议被设计出后就成为了消息中间件协议的开放标椎。任意的用户基于AMQP协议都可以和AMQP供应商提供的消息中间件进行交互特点
独立于平台的底层消息传递协议
- 消费者驱动消息传递
- 跨语言和平台的互用性
- 有5种交换类型direct,fanout,topic,headers,system
- 长连接,并且在一个连接中打开多个Channel
- 面向缓存的
- 可实现高性能
- 支持长周期消息传递
- 支持经典的消息队列,循环,存储和转发
- 支持事务(跨消息队列)
- 支持分布式事务(XA,X/OPEN,MS DTC)
- 使用SASL和TLS确保安全性
- 支持代理安全服务器
- 元数据可以控制消息流
- 不支持LVQ
- 客户端和服务端对等
- 可扩展
模型
看上去是不是很眼熟,没错,RabbitMq就是一个标椎的AMQP协议的实现。
最重要的概念就是Visual Host,Exchange,Queue,具体参考:RabbitMq基础知识
数据结构
AMQP是一个基于帧的协议,包括方法帧、内容帧,心跳帧等
所有的帧都由一个头(7个字节),任意大小的负载(payload),和一个检测错误的帧(frame-end)字节组成
MQTT
MQTT全称Message Queuing Telemetry Transport,翻译为消息队列遥测传输协议起源
随着万物互联的时代来临,越来越多的小型设备,例如各种家电等也需要进行一些实时的消息传输,然而AMQP的操作相对来说比较复杂,小型设备的性能无法在规定的短时间内解析出AMQP消息的内容
此时MQTT出现了,MQTT的目的就是为了帮助小型设备,在低带宽,不稳定的网络环境下,进行高效稳定的消息服务特点
MQTT是基于发布订阅模式的轻量级协议,特点就是数据结构简单且高效,用极少的代码和有限的带宽,提供可靠的消息服务。
因为MQTT高效、简洁、低带宽的即时通讯性,其在物联网,移动通讯方面的有着极为广泛的应用模型
MQTT使用的发布/订阅消息模式,它提供了一对多的消息分发机制,从而实现与应用程序的解耦。
这是一种消息传递模式,消息不是直接从发送器发送到接收器,而是由MQTT Serve分发的。
数据结构
固定头(Fixed header)
存在于所有MQTT数据包中,表示数据包类型及数据包的分组标识,包括如下数据结构
Qos
Qos全称Quality of Service levels,翻译为服务质量等级。
为了避免网络不稳定带来的服务不确定性,MQTT通过Qos来优化消息传输的可靠性,即发送者发送几次消息给接收者
- 在消息发布时,发送者为Publisher,接收者为Broker
- 在消息消费时,发送者为Broker,接收者为Consumer
Qos包含以下取值
- 0:最多发送一次,即<=1,此时会出现消息丢失情况
- 1:至少发送一次,即>=1。此时会出现消息重复的情况
- 2:发送一次,即=1。理论上不会出现消息的重复或丢失,但是此级别带来的网络损耗最高
可变头(Variable header)
存在于部分MQTT数据包中,取决于数据包类型消息体(Payload)
存在于部分MQTT数据包中,表示客户端收到的具体内容
Payload消息体是MQTT数据包的第三部分,CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四种类型的消息存在消息体:
- CONNECT消息体:客户端的ClientID、订阅的Topic、Message以及用户名和密码
- SUBSCRIB消息体:一系列的要订阅的主题以及QoS。
- SUBACK消息体:服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。
- UNSUBSCRIBE消息体:要取消订阅的主题。
STOMP
STOMP全称Simple Text Orientated Messaging Protocol,翻译为简单面向文本消息协议数据结构
STOMP是一个基于帧(Frame)的协议,客户端与服务端通过发送不同的命令帧来开启或关闭链接,以及进行数据的交互
每个帧的结构如下
可以看出,每个帧都是由line(行)构成
- 第一行包含了命令,然后紧跟键值对形式的Header内容。包含如下命令
- CONNECT(链接)
- SEND(发送消息)
- SUBSCRIBE
- UNSUBSCRIBE
- BEGIN
- COMMIT
- ABORT
- ACK
- NACK
- DISCONNECT
- 第二行必须是空行。
- 第三行开始就是Body内容,末尾都以^@结尾。虽然STOMP是简单文本传输协议,但是body也是可以传递流数据的