MQTT 代理是否会重新传递来自订阅者的未确认的“QoS 1”消息?
从[规范]:
当客户端在 CleanSession 设置为 0 的情况下重新连接时,客户端和服务器都必须使用其原始数据包标识符 [MQTT-4.4.0-1] 重新发送任何未确认的 PUBLISH 数据包(其中 QoS > 0)和 PUBREL 数据包。这是唯一需要客户端或服务器重新传递消息的情况。
所以,是的,未确认的 QOS1 消息将被重新传递,但规范要求发生这种情况的唯一时间是客户端重新连接时。
虽然您具体说明您使用的是 MQTT v3.1.1,但我认为值得注意的是MQTT v5明确禁止重新交付,而不是遵循重新连接:
当客户端重新连接并将 Clean Start 设置为 0 并且存在会话时,客户端和服务器都必须使用其原始数据包标识符重新发送任何未确认的 PUBLISH 数据包(其中 QoS > 0)和 PUBREL 数据包。这是唯一需要客户端或服务器重新发送消息的情况。客户端和服务器不得在任何其他时间重新发送消息
MQTT 代理重新交付之前必须经过多长时间?
根据上述规范,不需要自动重试。一些经纪人可能会在一段时间后重新传输。emqx支持这个;mosquitto 曾经有一个选项,但在 1.5 版中已删除,更改日志解释为:。
QoS>1 的传出消息在超时后不再重试。当客户端重新连接时,将重试消息。通过考虑何时可能发生超时,可以证明这种行为变化是合理的。
- 如果连接不可靠并且已断开,但没有注意到一端,则将在重新连接时重试消息。发送额外的 PUBLISH 或 PUBREL 不会改变任何东西。
- 如果客户端过载/无法响应/连接速度很慢,那么发送额外的 PUBLISH 或 PUBREL 将无助于客户端赶上。一旦积压已清除,客户端将响应。如果它无法赶上,发送额外的副本也无济于事
MQTT 代理是否无休止地尝试重新传递未确认的消息?
3.11 规范没有提供任何指导(因此,理论上是的),但许多代理对此提供了一些控制(排队的最大消息数、队列的最大大小等)。
还有其他方法可以触发重新交付吗?
是的 - 断开并重新连接。
推迟发送 PUBACK 直到成功保存收到的消息是一个好/有效的主意吗
几个月前,paho-dev 小组对此进行了讨论。Go v5 客户端正在考虑它(当前客户端自动确认消息)。
需要注意的一件事是 MQTT 规范确实对发送的订单确认有要求。许多客户端忽略了这个要求(并且只要处理程序返回就发送确认),但是一些(例如HiveMQ Java 客户端)排队 ACK 以便它们可以以正确的顺序发送。