Loading

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条

posted @ 2022-10-10 09:07  eiSouthBoy  阅读(7328)  评论(0)    收藏  举报