【问题标题】:Mosquitto QoS2 bug - or subtle spec interpretation?Mosquitto QoS2 错误 - 或微妙的规范解释?
【发布时间】:2020-10-17 18:59:13
【问题描述】:

谁能解释为什么这个 MQTT QoS 消息永远不会被发送? ANSWER:需要在 conf 文件中设置 persistent true,然后会出现确切的预期行为。

更多细节

我有一个简单的问题(尽管起始条件很复杂)。如果答案是“是”,那么 mosquitto 中存在一个错误,如果“否”,那么它是对我(我怀疑许多其他人)没有完全掌握的规范的非常微妙的解释。在第二种更可能的情况下,这意味着不可能在单个设备上使用 sub 和 pub 为同一主题编写完全符合 QoS2 的“序列测试器”。

设置 订阅 T @ QoS2 并每次都开始 clean==false 的代码。每 1 秒发布一个整数值递增的 T,这样在正常操作过程中,事件的顺序是:

  • 客户端 -> 服务器 TX 1
  • 服务器发布 1
  • RX 1
  • TX 2
  • 服务器发布 2
  • RX 2

然后我故意以随机间隔断开与服务器的连接,以测试我的恢复过程。

重新启动时,我的测试客户端正确识别失败的 TX,因为它已存储状态,例如TX3 失败并重新发送,当然 mosquitto 重新确认......无论使用什么术语,如果中断位于 TX 4 路的中间,我的代码会正确恢复,如果它位于 RX 4 路的中间然后 mosquitto 立即“恢复”它自己失败的 TX,一切都按预期进行。我从来没有得到任何 N 的“遗漏”值,我声明我的代码完全正常工作。那我的问题是什么?

连接中断/重启行为异常 考虑一下何时 TX 和服务器 pub 之间的连接完全中断(我的下一个 RX 将是什么),即 TX3 完全成功 PUB/REC/REL/COMP,如果没有中断,我将打印“RX 3”。接下来我使用 mqtt-spy 发布 T[666]。然后我重新启动我的客户端。我得到的第一件事是来自服务器的 666 消息,这听起来对我来说是正确的,并且似乎同意:

当服务器获得传入应用程序消息的所有权时,它必须将其添加到具有匹配订阅的客户端的会话状态中。匹配规则在第 4.7 节 [MQTT-4.5.0-1] 中定义。 和

[MQTT-3.1.2-4] |如果 CleanSession 设置为 0,服务器必须恢复 基于当前会话的状态与客户端通信 (由客户标识符标识)。如果没有会话 与客户端标识符相关联的服务器必须创建一个新的 会议。客户端和服务器必须在客户端之后存储会话 和服务器断开连接。

但我再也见不到RX3了。

当然,同样的规则也适用于 TX3?服务器在发布我时获得了所有权,并且必须将其添加到我们当时共享的开放会话中,因此它知道我是尚未向其发送该消息的 QoS2 订阅者,方式与666,因此 - 按照我的逻辑 - 我必须接收重新发送的 RX3 以及 666?

除了 mosquitto 在未能重新发送 T[3] 时出错之外,唯一对我有意义的事情是对这个词的进一步解释:

[MQTT-3.1.2-5] |断开连接后的会话 CleanSession 设置为 0,服务器必须进一步存储 QoS 1 和 QoS 2 与客户端当时拥有的任何订阅相匹配的消息 断开连接作为会话状态的一部分。

我看到 666 是如何“进一步”的,因为它发生在休息之后。我还看到 3 是在休息之前,因此不是“进一步”......所以你可以争辩说 moz 不应该被要求在重新连接到同一个会话时提供,但我仍然说 moz 没有履行其对我的 QoS2 承诺,如果它没有,因为我曾经并且仍然是同一会话中该主题的订阅者,它知道它没有向我发送实例,无论它来自哪里!

如果这是正确的并且 moz 中没有错误,那么这意味着在物理上不可能在同一设备上编写具有 RX 和 TX 的背靠背 QoS2 测试程序......或者更准确地说,在同一个设备上会议。正如我的示例(以及我的许多wireshark 日志)最终证明消息3 永远不会在重新连接时发送。因此,我的测试人员“错过”了一个事务对并声称 QoS2 失败。具有讽刺意味的是,如果我将 TX 和 RX 放在两个单独的程序中,那么仅 RX(没有崩溃)肯定会收到它并保持“同步”并声称连续 QoS2 成功?我还没有对此进行测试,并会等待看看我是否首先在这里得到一个有用的答案,以确保我没有遗漏任何东西(除了 RX[3] :))

这似乎是矛盾的

Server 中的 Session 状态包括:

· 一个Session的存在,即使剩下的Session 状态为空。

· 客户的订阅。

· 已经发送给客户端的QoS 1和QoS 2消息, 但还没有被完全承认。

· QoS 1 和 QoS 2 消息等待传输到客户端。

· 已经从客户端收到的 QoS 2 消息,但是 还没有完全承认。

我看不出有什么理由说我丢失的 RX3 不是“等待传输到客户端的 QoS 1 和 QoS 2 消息”。无论是“进一步”还是其他!

最后,在同一点上,当 moz CONNACKs 设置会话时,这实际上意味着什么?我认为它的意思是它认为它有一些存储的会话需要重播,在这种情况下,我看到的下一件事应该是传入的 pubrel 等。当 session==true 但服务器没有发送任何内容时,这是什么意思?是告诉我它认为我应该有一些存储的会话数据需要重播吗?如果是这样,为什么?我已经知道了,因为 - 就像一个好孩子 - 我已经存储了会话状态,我在重新连接时会重播,所以我不需要被告知!对我来说, session==true 应该只意味着一件事:“等待一些传入的重播请求”......如果它再次出现,那么我看到 session==true 存在一个错误,并且在大多数情况下没有任何传入。如果不是,那我又很困惑,我欣然承认这是最有可能的答案……但是:

在上面的例子中,蚊子是否应该在“脏会话”重新连接时发送 TX[3]?如果没有,为什么不呢?

【问题讨论】:

  • 我需要花一点时间来消化这个,但是快速测试一下。如果您将 mosquitto 换成其他经纪人会怎样?
  • “我必须在收到 666 之前收到 RX3 重新发送?”不....订单不保证,只是交货。还要记住:Mosquitto 不是一种 HA 类型的服务器。如果 QoS2 消息进入,并且您在此时使服务器崩溃,它可能没有时间将数据包写入文件......因此当它恢复时,没有 QoS2 消息要处理。 Mosquitto 日志文件说明了什么?您将从中获得比数据包跟踪更多有用的信息。
  • @jdallen 我的语法错误 - 我理解“订单”问题。事实是我根本没有得到 RX3,所以订单与问题无关。 Alos 听到你关于崩溃时间的观点,但这正是我的观点,mosquiito 不应该发布我,直到它处于随后交付的位置。因此,故障点将位于 txn 的中间,并且会成功恢复。如果您的情况是允许的,那么 QoS2 保证是不可能的,因此恕我直言 - 100% 损坏
  • @JD Allen 我将编辑 Q 以删除“之前”
  • @Phil Bowles 请务必回答您自己的问题,并将其设置为已为其他人回答,而不是可能有一天有相同的问题。

标签: session mqtt mosquitto


【解决方案1】:

解决方案是向 mosquitto.conf 文件添加持久真实

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 2011-10-22
    • 1970-01-01
    • 2011-03-27
    相关资源
    最近更新 更多