MQTT 消息持久化&&离线消息接收
前提条件:服务器(EMQX)& 生产者 都正常工作--消费者正常或者非正常掉线,一段时间过后,消费者重新上线,如何保证接收掉线时间内的离线消息?
一、持久化会话
当消费者连接服务器时,通过关键字段
告知服务器需要持久化会话。服务器记住该消费者-客户端,并保留持久化会话信息。
当该消费者重新上线时,无需重新订阅topic,直接消费消息(包括离线消息)。
客户端和服务端可以保存会话状态,以支持跨网络连接的可靠消息传输。清理会话标志位:Clean Session
用于控制会话状态的生存时间
🔶 清理会话(CleanSession)标志被设置为0
/* 情形一 */
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
conn_opts.cleansession = 0;
服务端必须基于当前会话(使用客户端标识符识别)的状态恢复与客户端的通信。如果没有与这个客户端标识符关联的会话,服务端必须创建一个新的会话。在连接断开之后,当连接断开后,客户端和服务端必须保存会话信息。
当清理会话标志为0的会话连接断开之后,服务端必须将之后的QoS 1和QoS 2级别的消息保存为会话状态的一部分,如果这些消息匹配断开连接时客户端的任何订阅 。服务端也可以保存满足相同条件的QoS 0级别的消息
🔶 清理会话(CleanSession)标志被设置为1
/* 情形二 */
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
conn_opts.cleansession = 1;
客户端和服务端必须丢弃之前的任何会话并开始一个新的会话。会话仅持续和网络连接同样长的时间。与这个会话关联的状态数据不能被任何之后的会话重用
二、离线消息接收
2-1 情形一
情形描述:生产者正常发布消息,消费者正常订阅消息。一段时间,消费者离线,然后重新上线。
(注意:情形描述的先后顺序很重要;若生产者发布消息,一段时间后,生产者离线,消费者上线,此时消费者是无法订阅离线消息的)
🔶 正常收发
消费者log日志
2022-10-09 17:34:14.52
message: 2022-09-09 17:34:14...0
----------------------------------
2022-10-09 17:34:14.53
message: 2022-09-09 17:34:14...1
----------------------------------
2022-10-09 17:34:14.64
message: 2022-09-09 17:34:14...2
----------------------------------
2022-10-09 17:34:14.75
message: 2022-09-09 17:34:14...3
----------------------------------
2022-10-09 17:34:14.86
message: 2022-09-09 17:34:14...4
----------------------------------
......(此处省略)
2022-10-09 17:39:38.62
message: 2022-09-09 17:39:38...2992
----------------------------------
2022-10-09 17:39:38.73
message: 2022-09-09 17:39:38...2993
----------------------------------
2022-10-09 17:39:38.84
message: 2022-09-09 17:39:38...2994
----------------------------------
🔶 消费者离线一段时间后,再次上线
消费者离线时,消费最后一条消息:message: 2022-09-09 17:39:38...2994
消费者log日志
2022-10-09 17:43:17.14
message: 2022-09-09 17:39:38...2995
----------------------------------
2022-10-09 17:43:17.15
message: 2022-09-09 17:41:28...4003
----------------------------------
2022-10-09 17:43:17.15
message: 2022-09-09 17:41:28...4004
----------------------------------
2022-10-09 17:43:17.16
message: 2022-09-09 17:41:28...4005
----------------------------------
......(此处省略)
2022-10-09 17:43:36.06
message: 2022-09-09 17:43:35...5177
----------------------------------
2022-10-09 17:43:36.17
message: 2022-09-09 17:43:36...5178
----------------------------------
2022-10-09 17:43:36.27
message: 2022-09-09 17:43:36...5179
----------------------------------
🔶 数据分析
消费者重新上线后,消费第一条消息:message: 2022-09-09 17:39:38...2995
,第二条消息:message: 2022-09-09 17:41:28...4003
由此可见,消费者上线后虽然能消费离线消息,但也出现离线消息丢失:2996~4002之间的数据丢失
。
原因:可能是mqtt 服务器缓存队列有限制,缓存数据超出约定大小后,丢弃部分旧数据,存放新数据。
2-2 情形二
情形描述:生产者发布消息:0~2000,停止消息发布;消费者开始消息消息
消费者log日志
2022-10-10 10:39:34.02
message: 2022-09-10 10:38:36...1001
----------------------------------
2022-10-10 10:39:34.03
message: 2022-09-10 10:38:36...1002
----------------------------------
2022-10-10 10:39:34.04
message: 2022-09-10 10:38:36...1003
----------------------------------
......(此处省略)
2022-10-10 10:39:40.85
message: 2022-09-10 10:38:53...2000
----------------------------------
2022-10-10 10:39:40.85
message: 2022-09-10 10:38:53...2000
----------------------------------
2022-10-10 10:39:40.86
message: 2022-09-10 10:38:53...2000
----------------------------------
分析消费者日志可知:消费者只消费消息:1001~2000,故mqtt服务器(即EMQX)消息缓存队列大小为:1000条