想象一下客户端连接了一段时间,定期将消息发布到它的主题中。然后连接断开,并且很长一段时间不可用(例如,由于硬件问题)。调用 mosquitto 库的客户端代码继续发布消息。在这种情况下会发生什么?
- 我怀疑如果我调用 mosquitto 循环,它会尝试重新连接,如果成功,它将处理所有积压的发布命令?
- 或者,在某个时间点,发布例程将开始返回“未连接”错误?
- 如果不是以上,即使在网络不可用状态下,mosquitto 客户端仍然会接受调用 mosquitto_publish() 来发布消息 - 那么限制在哪里?
- 我在内存方面调用 mosquitto_publish() 后如何执行库代码 - 应该提供数据缓冲区完整,直到客户端应用程序收到发布操作的确认,或者 mosquitto_publish() 在内部将消息复制到其缓冲区,并且应用程序可以修改用于调用的缓冲区mosquitto_publish() 并使用相同的缓冲存储器执行下一个 mosquitto_publish()?
- 如果 mosquitto_publish() 使用自己的缓冲区,并且网络不可用,我怀疑它将为发布消息分配越来越多的内存 - 应用程序如何跟踪减少的可用内存以及时停止调用 mosquitto_publish() 以防止机器因以下原因而崩溃可用内存不足?
在mosquitto.h和协议文档中找不到与这些问题相关的信息。我还怀疑不同的 MQTT 实现可能会有不同的表现。
此外,在库无法向代理发送数据的情况下,是否有关于发布消息和管理的流程描述?
顺便说一句,我尝试使用这种方式,但是在后台进程运行时查看总可用内存并没有帮助,而且通常甚至不知道 mosquitto_publish() 如何管理其分配的内存。
更新:(不知道为什么这个问题我得到-1)
我能够使用我指向的代码模拟空闲内存缩减,连接到代理而不执行循环例程。最后机器必须崩溃,或者变得几乎无法操作。
那么灭蚊码有哪些措施呢?
- 定期调用
mosquitto_loop
,谢天谢地可能会返回MOSQ_ERR_NO_CONN
错误,允许应用程序停止发布。MOSQ_ERR_NO_CONN
问题 -赶上的速度有多快,在内存溢出之前有什么保证? - 使用
mosquitto_loop_start
,我不知道如何从它或从库中获取网络状态 - 唯一的方法是使用回调。但是如果库仍然尝试通过非操作连接发布,则不会发生发布回调,并且没有连接丢失的回调来通知应用程序停止发布。
即使应用程序能够评估 mosquitto 库占用的内存大小,或者通过它尝试发布的消息的数量(或累积大小)来跟踪大小,那么有一个很好的问题 - 如何从传感器累积数据,并且如果应用程序能够管理已发送以供发布但未发布的消息,以将它们从 mosquitto 库队列中删除并替换为较新的遥测消息。
更新:我对这个问题做了进一步的研究。行动的过程是:
- 连接到经纪人;
- 循环中:发布一条消息,检查可用内存大小,然后调用
mosquitto_loop(mosq, 0, 1);
我在飞行中看到消息为 20,但此选项与本地队列中等待发送到代理的消息无关。只要客户端连接到代理,它就可以定期向代理发送消息,因此内存空闲大小缩小相对缓慢。但是,一旦我物理断开上游连接(通过拔出 3G 天线 - 模拟硬件故障),该算法就无法再向代理发送消息,并且 mosquitto 库继续收集发布请求。通过这种方式,我可以很快将 67 MB 的可用系统 RAM 降至 1.8 MB。好消息是机器没有崩溃,剩余时间我运行测试的可用空间保持在 1.8 MB。
值得注意的是,没有人调用 -mosquitto_publish()
也没有mosquitto_loop()
返回指示没有网络的错误(我预期MOSQ_ERR_CONN_LOST
的错误),因此我的测试应用程序不知道库无法向代理发送消息,并且我的应用程序无法确定何时必须暂停发布进入mosquitto_publish()
并开始执行替代操作(例如,将消息写入存储设备以供稍后发布。
更新:可能有一种方法可以在应用程序的主循环中评估发布进度(在决定继续发布之前) - 使用消息 ID。但是这种方法依赖于函数连续发送消息的假设mosquitto_publish()
(否则这将需要跟踪每条消息)。我没有在标准或蚊子呼叫描述中看到这一点。
更新:我对文档有误 - 它有关于消息排序的章节“4.6 消息排序”。因此,我认为mosquitto_publish()
使用发布的最后一个消息 ID 与通过回调指示的消息 ID 来评估函数缓冲的消息数量必须是可靠的。