MQTT 系列(四)MQTT v5.0 新特性

为什么MQTT v3、v3.1.1 之后变成 v5.0,而没有 v4 ?MQTT 协议数据包的固定头中含协议版本,协议版本只占一个字节位置。在v3.1.1版本中就使用了 ‘4’ 这个值,所以为了这个值与版本名称的同步,此版本 MQTT 命名为 v5.0,使用值 ‘5’ 表示此版本。


Clean Start

MQTT v3.1.1 Clean Session VS MQTT v5.0 Clean Start

Clean Start 与 Clean Session 一样是一个标志。Clean Start 为 1 时,客户端和服务端必须丢弃任何已存在的会话,并开始一个新的会话,与 Clean Session 类似。Clean Start 为 0 时,并且存在一个关联此客户端标识符的会话,服务端必须基于此会话的状态恢复与客户端的通信。如果不存在任何关联此客户端标识符的会话,服务端必须创建一个新的会话。

Clean Start 简化了会话处理,比 Clean Session 更容易实现。除非会话过期时间为 0 ,否则所有会话仍是持续的。会话的删除发生在超时后或当客户端重新连接到 “Clean Start” 时。

Clean Start 代替了 Clean Session,不再用于指示是否存储会话状态,仅用于指示服务端在连接时尝试恢复会话还是创建新会话。会话状态在服务端的存储时长由 Session Expiry Interval 决定


会话过期时间 Session Expiry Interval

  • 单位:秒

  • 设置为 0 或者未指定,会话在网络连接关闭时结束

  • 设置为 0xFFFFFFFF ,会话永不过期

  • 网络连接关闭时,值大于 0 则客户端与服务端存储会话状态


消息过期时间 Publication Expiry Interval

为每一个消息或设置一个时间限制,指定消息多久后过期,时间到达后该消息将会被删除,Broker 就不会将已过期的消息发送到 Client,单位同样是秒。


用户属性 User Properties

在 MQTT v3.1.1 中 ClientA 收到一条消息,想对该消息发布者反馈一条消息,但是并不知道是谁发送的。解决方法是,消息发布的时候在消息数据中填上自己的信息,打包后 Publish。而在 v5.0 版本,用户信息包含在 User Properties ,无需放在数据中。


共享订阅 Shared Subscriptions

多个 Client 可以订阅同一主题,这个主题的消息可以均衡的分别发送给这些 Client ,实现订阅的均衡负载,提高消息的吞吐量。在旧版本中多个 Client 订阅同一主题,所有Client 都会收到消息,并没有均衡负载功能。旧版本解决办法是 每一个 Client 订阅不同的 Topic ,发送者依次 Publish 到不同的 Topic ,尽管是同一类型的数据…

共享订阅的主题结构如下:

$share/所属组/[Topic Name]


重复主题

在 MQTT 3.1.1 和之前的版本里,PUBLISH 数据包每次都需要带上发布的主题名,即使你每次发布的都是同一个主题。

在 5.0 里面,如果你将一条 PUBLISH 的主题名设为长度为 0 的字符串,那么 Broker 会使用你上一次发布的主题。这样降低了多次发布到同一主题(往往都是这样)的额外开销,对网络资源和处理资源都有限的系统非常有用。


主题别名 Topic Alias

通过将主题名缩写为小整数来减小MQTT报文的开销大小。客户端和服务端分别指定它们允许的主题别名的数量。


遗嘱延迟 Will Delay

提供指定遗嘱消息在连接中断后延时发送的能力。设计此特性是为了在会话的连接重建的情况下不发送遗嘱消息。此特性允许连接短暂中断而不通知其他客户端。


增强验证

MQTT 报文中可以设置用户名与密码来验证,服务端通过这个信息来判断客户端是否合法,这是简单验证。简单验证占用服务资源少,但安全性并不高。增强验证为 MQTT v5.0 新特性,实现双向验证(质询-响应),即客户端验证服务端,服务端也验证客户端,通常使用 SASL 机制。


双向 DISCONNECT

在 3.1.1 和之前的版本里,只有 Client 在主动断开时会向 Broker 发送 DISCONNECT 包。如果因为某种错误 Broker 要断开和 Client 的连接,它只能直接断开底层 TCP 连接,Client 则不会知道自己连接断开的原因,也无法解决错误,只是简单地重新连接、被断开、重新连接…

在 5.0 里面,Broker 在主动断开和 Client 的连接时也会发送 DISCONNECT 包。同时,从 Client 到 Broker,以及从 Broker 到 Client 的 DISCONNECT 包里面都会包含一个 Reason Code,来标识断开的原因。