MQTT一些容易忘记的概念

英文还可以的话,建议阅读:MQTT Essentials

 

Clean Session

clean session告诉broker客户端(client)是否想要建立一个持久会话。一个持久会话(Clean Session设为false)的意思是,broker将为这个client保存所有订阅相关的和所有错失的消息,不过前提是client以QoS为1或2进行订阅。如果Clean Session为true,broker将不为client保存任何信息,并且清除这个client之前所持持久会话的所有信息。

Will Message

will message是MQTT的遗嘱消息,当某个client非正常断开连接时,通过它可以告知其他client这个事件。一个正在连接的client通过一个MQTT消息提供它的遗嘱消息,并且其topic在CONNECT消息中提供。如果这个client异常断开时,broker将为这个client代发这个遗嘱。而broker也会在client正常断开连接时,会将LWT消息丢弃。

KeepAlive

keep alive是一个间隔时间,clients承诺每间隔这么多时间会给broker发送PING请求消息,broker同时也返回一个PING响应信息。这个机制使得两边可以判定对方是否可达。

QoS 0 – at most once

最低级别QoS是0,它提供的保证是尽力而为。一个消息发送出去,不会得到接收者的确认或保存,发送者也不会重发。这种方式一般被称为“触发&忘记”,提供的保证类似于底层的TCP协议。

QoS 1 – at least once

使用QoS级别为1时,会保证消息会发送到接收者那边,但消息有可能会被发送多次。

QoS 2 – exactly once

最高Qos级别为2,它保证每个消息被对方接收一次,这是最安全也是速度最慢的方式,因为要做更多的确认工作。

QoS降级

发布者和订阅者可以使用不同的QoS级别,比如client A发布一个消息,client B接收该消息时,A和broker之间的QoS由A决定,而当broker将消息发送给接收者时,会使用B的QoS。如果B订阅时指定了QoS为1,A发送时指定QoS为2,那消息会以QoS为1发送到B,这时候消息也有可能多次发送到B,因为QoS为1时是至少发送一次。

使用QoS 0的场景

  1. 发送者和接收者之间有一个稳定的连接,典型的场景就是一个测试客户端或者某个前端应用通过有线的方式连接到MQTT broker。
  2. 不在乎一个或多个消息偶尔的丢失。
  3. 不需要将消息保存到队列的时候。只有那些QoS为1或2并且拥有持久会话的client断开连接时,消息才需要被缓存到队列。

使用QoS 1的场景

  1. 你需要接收到所有消息,并且接收者可以处理重复消息。
  2. 你承受不了QoS 2的额外负担,QoS 1性能会好很多。

使用QoS 2的场景

  1. 你的应用需要接收到所有消息,并且每个消息只接收恰好一次,重复消息会导致你的应用出现某些问题。

缓存QoS 1和2的消息

所以QoS为1和2的消息会在client离线时被放入队列,直到它们重新上线。不过放进队列的前提是,client拥有一个持久会话。

Retained Messages

retained message也是一个普通的MQTT消息,只是将retained标志设置为true。broker将保存最后接收到的retained消息及其QoS。client订阅时如果topic和这个retained消息的topic匹配,则在订阅成功后马上收到该消息。对于每个topic,broker只保留一个retained消息。

订阅的client不需要精确匹配topic,比如它可以使用通配符。比如A发布一个retained消息到myhome/livingroom/temperature,B订阅了myhome/# ,B也会收到A发送的retained消息。client接收到消息时,可以通过retained标志位(broker设置)判断这个消息是否是retained消息,然后进行相应的处理。

retained消息也是那种“last known good value”,它不是最后一个消息,但确实是最后一个retained标志位被设置为true的消息。新订阅的client马上收到这个消息,而不用等发布者再次发布,一个应用场景就是程序的版本更新,客户端一连接就得到应用是否有更新的消息。

值得一提的是,retained消息和持久会话没有任何关系。

broker何时发送LWT message?

根据MQTT 3.1.1 specification,broker会在以下几种情况发送LWT:

  1. 服务器发现I/O错误或者其他网络问题。
  2. client在keep alive时间内没有通讯。
  3. client关闭网络连接,但这之前没有发送DISCONNECT包。
  4. 服务器因为协议错误关闭了网络连接。

最佳实践 – 何时使用LWT?

LWT适用于需要通知clients某个连接的断开。在真实的场景中,LWT往往会和retained消息一起使用,是为了将client的状态保存在某个特定的topic中。

最佳实践

什么时候使用persistent session?什么时候使用clean session?

Persistent Session

  1. client必须从某个topic获取到所有消息,即使它已经离线。broker必须将消息放进队列,等到client重连时立即发送这些消息。
  2. client资源有限,broker需要保存它的订阅信息,这样通讯可以迅速恢复。
  3. client重连后,需要处理所有QoS为1和2的消息。

Clean session

  1. client不订阅消息,只是发布,所发布QoS为1和2的消息也不需要重试。
  2. client不需要主动接收它离线时的消息.

session会保存哪些信息?

  1. session的存在性,即使没有任何订阅者。
  2. 所有订阅信息。
  3. 所有QoS为1和2的并且还没有得到client确认的消息。
  4. 所有QoS为1和2的新消息,这些消息到来时client正好离线。
  5. 所有接收到的QoS为2的并且还没有得到client确认的消息。

这就意味着即使client离线,broker也会保存以上信息,当client重连时,可以得到这些信息。

发表评论

电子邮件地址不会被公开。