MQTT协议学习心得

初识MQTT

到了物联网时代,由于智能硬件的差异,相比互联网终端,硬件配置要低的多,而且智能设备的环境也想多复杂,物联网中的数据传输会面临很多问题,比如在网络不稳定的情况下,如果保证数据的传输没有问题,如何保证数据不被重复发送,连接断开后如何进行重连,而HTTP协议由于太重量级了,不是适合物联网。因此IBM公司为此提出一种轻量级的MQTT协议。

MQTT(Message Queuing Telemetry Transport),是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。

如今很多第三方推送平台都采用了MQTT来实现,消息中间件ActiveMQ的订阅/发布模块也是基于MQTT实现的。

MQTT的实现模型

这里写图片描述

MQTT消息代理:即消息服务器,作用是处理客户端订阅/发布的请求 

MQTT客户端:需要注意的是,在MQTT的业务模型当中,消息发布者和消息订阅者都属于客户,也就是说一个客户既可以发布消息也可以订阅某个消息

主题名称(Topic name):用来标识已发布消息的信息的渠道。订阅者用它来确定接收到所关心的信息。它是一个分层的结构,用斜线“/”作为分隔符。有两种通配符可以在主题发布、订阅时使用:“#”和“+”。前者可以通配多层结构,而后者只能通配一层结构。例如一个topic : “a/b/c”,则“a/+/c”和“a/#”都可以和它相等。发布不支持模糊匹配,必须是确定的主题。

服务质量

在MQTT中用QoS表示服务质量,有以下三种取值: 
1)QoS=0,至多一次,可能会出现丢包的现象。使用在对实时性要求不高的情况。这一级别可应用于如下情景,如环境传感器数据,丢失一次读记录无所谓,因为很快下一次读记录就会产生。 
2)QoS=1,至少一次,保证包会到达目的地,但是可能出现重包。 
3)QoS=2,正好一次,保证包会到达目的地,且不会出现重包的现象。这一级别可用于如计费系统等场景,在计费系统中,消息丢失或重复可能会导致生成错误的费用。

报文格式

这里写图片描述

每个MQTT命令消息的消息头部都包含了一个固定头部。其中一些类型的消息可能还需要一个可变头部和一个有效载荷(可理解为消息体)。MQTT报文的固定头部只有2个字节,这也是相比其他协议更加轻量的原因。

BYTE1

包含消息类型和标志(包括DUP,QoS level和RETAIN)字段,QoS我们在上文中已经提过。现在我们看一下另外几个字段。

消息类型(Message Type)

标识 计数 描述
Reserved 0 保留
Connect 1 客户端到服务端的连接请求
ConnACK 2 服务端对连接请求的响应
Publish 3 发布消息
puback 4 对发布消息的回应
pubRec 5 收到发布消息(保证传输part1)
pubRel 6 释放发布消息(保证传输part2)
pubComp 7 完成发布消息(保证传输part3)
subscribe 8 客户端订阅请求
subBack 9 订阅请求的回应
unsubscribe 10 停止订阅请求
unsubBack 11 停止订阅请求响应
pingReq 12 Ping请求(保持连接)
pingResp 13 Ping响应
disconnect 14 客户端正在断开
reserved 15 保留

DUP 

当客户端或服务器试图重发 PUBLISH、PUBREL、SUBSRIBE、UNSUBSCRIBE 消息时,该标志位要被置位(即设为1)。这适用于消息的QoS标志值大于0的情况,此时消息确认是必需的。当DUP位被置位时,可变头部将包含一个消息ID。

消息的接收者应当将该标志视为该消息之前可能已收到的提示消息,而不该依赖于它进行消息重复检测。

RETAIN 

该标志位只用于 PUBLISH 消息。当一个客户端发送一条 PUBLISH 消息给服务器,假设该消息所属的主题(topic)为topicA,如果该标志位被置位(1),服务器在将该条消息发布给当前的所有topicA的订阅者之后,还应当保持这条消息

当topicA出现了一个新的订阅者,则topicA的最后一条保持消息应当发给该订阅者。当然,如果不存在保持消息,则什么也不用发。

当消息发布者以基于 “report by exception” 的方式发送消息时,这个功能就特别有用,因为这种情况下,消息发送间隔往往较长。这个功能使得新的订阅者可以立刻收到之前保持的或上一个确定有效的消息。

当服务器收到某个主题的 PUBLISH 消息时,对于之前已经订阅该主题的客户端,服务器将给这些客户端发送这一 PUBLISH 消息,发送前,服务器会将该消息的 RETAIN 标志置为0(即不置位),不管服务器之前收到该 PUBLISH 消息时其 RETAIN 标志是否被置位。这样做可以使得区分它接收到的 PUBLISH 消息是服务器之前保持的(RETAIN标志置位)还是即时收到的(RETAIN标志不置位)

保持消息应当在重启服务器后仍能保留

如果服务器收到有效载荷长度为0或重复主题的保持消息,服务器可以删除该保持消息。

BYTE2

该字段表示当前消息的剩余内容的字节数,包括可变头部和有效载荷的数据

三类QoS的实现方式

QoS=0时,并且它保证一次信息尽力交付。一个消息不会被接收端应答,也不会被发送者存储并再发送。这个也被叫做“即发即弃”。并且在TCP协议下也是会有相同的担保。 
这里写图片描述

QoS=1时,消息最少发送1次,它保证信息将会被至少发送一次给接受者。但是消息也可能被发送两次甚至更多。发送者将会存储发送的信息直到发送者收到一次来自接收者的PUBACK格式的应答。PUBLISH 与PUBACK的关联是通过比较数据包中的packet identifier完成的。如果在特定的时间内(timeout)发送端没有收到PUBACK应答,那么发送者会重新发送PUBLISH消息。如果接受者接收到QoS为1 的消息,它会立即处理这里消息,比如把这个包发送给订阅该主题的接收端,并回复PUBACK包。The duplicate(DUP)flag,用来标记PUBLISH 被重新分发的情况。仅仅是为了内部使用的目的,并且当QoS 为1 是不会被broker 或者client处理。接受者都会发送PUBACK消息,而不管DUP flag。 
这里写图片描述

QoS=2时,它会确保每个消息都只被接收到的一次,他是最安全也是最慢的服务等级。如果接收端接收到了一个QoS 的PUBLISH消息,他会适当地处理这个消息并发送一个PUBREC的包去通知broker。直到他发出一个PUBCOMP包为止,接收端都保存这个包packet identifier。这一点很重要,因为它避免了二次处理同一个PUBLISH包。 当发送者接收端PUBREC的时候,它可以放弃最开始的publish了,因为它已经知道另一端已经接收到消息,他将保存PUBREC并且回复PUBREL。当接收端接收到PUBREL,它就可以丢弃所有该包的存储状态并回复PUBCOMP。当发送端接收到PUBCOMP时也会总同样的处理。 
这里写图片描述

在这里要注意一点,QoS流在发送端和接收端是两件不同的事情,当然发送端与接收端QoS的等级也可以不一样在发送端与broker之间,发送端定义了QoS等级。当broker发送消息到接收端是,接收端决定了QoS的等级

到这里MQTT一些重要的知识点就罗列得差不多了,还有一些具体的细节有需要的可以自行百度下MQTT的文档(有中文的)

展开阅读全文

没有更多推荐了,返回首页