MQTT协议基础(6):MQTT协议中部分特殊设置
MQTT协议中部分特殊设置Retained消息、LWT机制、Keepalive机制、连接保活等
Retained消息
作用
在发布订阅模式下,如果订阅者订阅的时间刚好在发布者发布消息之后,那么订阅者就必须等待下一条消息,在这段时间内,订阅者处于信息真空时期。
为了避免这一现象,提出了Retained消息的概念。其具有如下的特点
1.一个Topic只能有一条Retained消息,新的Retained会覆盖旧的Retained消息
2.如果订阅者采用通配符订阅主题,那他会收到所有匹配主题的Retained消息
3.只有新的订阅者才会收到Retained消息,如果一个订阅者重复订阅一个主题,那么在每次订阅时都会被当做新的订阅者,然后收到Retained消息
具体设计
操作方法就是在PUBLISH数据包上将Retained标识置1,Broker收到这个消息后将为该主题保存这个消息,当一个新的订阅者订阅该主题时,Broker会马上把这个消息发送给订阅者。
另:当Retained消息发送到订阅者时,PUBLISH数据包中Retain标识仍为1,这样订阅者就能判断是否为Retained消息,做出相应处理。
如果想删除某个主题的Retained消息,只需要向这个主题发布一个Payload为空的Retained消息即可。
LWT(Last Will and Testament)
包括遗愿主题,遗愿QoS,遗愿消息等。所谓遗愿是指Broker检测到Client非正常地断开连接时,向遗愿主题发布一条消息。其相关的设置是在CONNECT数据包中指定的。
- Will Flag 是否使用LWT
- Will Topic 遗愿主题,注意不可以使用通配符
- Will Q is 发布遗愿消息时的QoS等级
- Will Retain 遗愿消息的Retain标识
- Will Message 遗愿消息内容
Broker在以下情况下会认为Client是非正常断开连接的
- Broker检测到底层I/O异常
- Client未能在Keepalive的时间间隔内和Broker之间进行消息交互
- Client在关闭底层TCP连接前没有发送DISCONNECT数据包
- Broker因为协议错误关闭了和Client的连接,比如Client发送了一个格式错误的MQTT协议数据包
如果Client通过发布DISCONNECT数据包断开连接,这属于正常断开连接,不会触发LWT机制。
Keepalive机制
MQTT协议是建立在TCP协议之上的应用层协议,当TCP协议断开时会通知上层应用层协议,但TCP协议存在一个半打开连接状态,这是非常不利的,会导致其中一端误以为连接依然存在。造成资源浪费。
为快速得知连接状态,设计Keepalive机制,在建立连接时设置Keepalive参数,MQTT协议规定在1.5个Keepalive时间间隔中如果没有信息交互,会认为彼此之间已经断开连接。
MQTT协议中设计一对PINGREQ/PINGRESP数据包来满足Keepalive的约定和连接状态的检测。
Keepalive机制的其它特性
- 如果在一个时间间隔内已经有了消息交互,那就没必要发送心跳包了
- Keepalive的值是有Client来指定的,不同Client可以指定不同的值
- Keepalive的最大值为18小时12分15秒
- Keepalive的值如果设置为0,代表不使用Keepalive 机制。
连接保活
一般Client的连接保活
这种情况下,直接在检测到断开连接之后,重新发起连接即可移动端的连接保活
移动端最大的问题在于,当手机软件切入后台之后如何保活?iOS客户端的方案
借助苹果的APNs发送推送消息。具体流程如下
当iOS系统中的APP被切入后台,接收MQTT协议消息的方式是1
2
3
4
51.Publisher发布一条或多条消息
2.Publisher通过某种途径告知APP的应用服务器,然后服务器通过苹果的APNs向对应的iOS订阅者推送一条消息
3.用户点击推送,APP进入前台
4.APP重新建立和Broker的连接
5.APP收到Publisher刚刚发送的消息Android客户端的方案
一方面可以采用类似上述的推送机制,比如华为推送,小米推送。
同时,也可以利用Android后台运行Service代码,在Service中创建和保持MQTT协议连接。