Message retry upon loss of packets in QOS1, without reconnection

Hello, I am currently working on a use case where if a qos1 packet from a broker to subscriber does not get acknowledged, the broker must retry sending the packet. However, this behavior is not observed(it was removed in mqtt 5)

So can someone enlighten me on the following points:

  1. Is loss of packet possible in TCP? is this a scenario that can happen
  2. If there is loss of PUBACK packet from subscriber to broker(considering it can happen), what is the recovery procedure? (ASSUMPTION: CLIENT DOES NOT RE-CONNECT, IT STAYS CONNECTED, meaning there is no message retry from the broker)

Hi Kushagra,

  1. On the TCP level, it should not be able to lose packages. The only option is that there is a disconnect happening.
  2. I am not sure on what changes you exactly refer to. Could you link the part you mean from the Oasis Standard? QoS1 you use if you need to confirm that a message has arrived. This is needed e.g. when you need to make sure you have processed a message and acknowledge this to the broker.
    The broker will resend the message if there is no acknowledgment from the client.
    This process can only be stopped if the client does not react within the keep-alive interval (broker will disconnect the client) or the client reaches the inflight message limit.
    There is an inflight limit for each client, which will not accept more messages than the queue is sized (20). This is usually plenty if a client is connected.
    I am not sure what you mean by there is no message retry. QoS1 is exactly designed so that there is a retry. Could you clarify this, please?

Best

Tizian

Thanks Tizian.

To setup the context, we are working on a safety critical system where we don’t expect any loss of single message. Ideally, with TCP (as its reliable tx mechanism), connection manager has to retransmit the packets. Consider a scenario like for some reason the packet (puback) sent by subscriber is lost before reaching to broker and in that case, how the system will be recovered. Can you please help in answering this?

If a QoS1 message is not acknowledged, the broker will resend it, even if the subscriber technically acknowledges it. If necessary for you: QoS2 will help you not to send double messages.

This scenario does not sound very likely though and it seems, that this scenario will more likely will result in a connection drop.

To not start fresh after a reconnect, make sure to use persistent sessions with the same client id, so the broker knows the state of the connecting client.

Thanks Tizian for quick response.

But, with MQTT 5.0 version, we could see that broker will not retransmit the packet if there is a loss of puback packet from subscriber. So, how can system be recovered in this case? Believe, this is same with QOS1 and QOS2.

This does not sound like an expected scenario.
I will talk to some colleagues and see what their insight is, but I will need some more information for this:

  • What broker version are you using?
  • Could you add the logs (log_type all), please so I can see what is happening

If you don´t want to share your logs in the forum, please contact us at support@cedalo.com
Thank you for sharing :slight_smile:

Mosquitto version: 2.6.5

  1. Screen1: max_inflight_messages is 1, so if the subscriber (left) does not send a PUBACK (with message auto ack disabled), the broker will send one message, and keep waiting for its acknowledgement, and traffic gets stuck there
  1. Screen2: If max_inflight_messages is 1000, the broker does not retry sending the un-acknowledged messages , unless the subscriber (persitent) is closed and started again

(note that the message d1 flag means duplicate messages, i.e, messages that were not acknowledged so were kept in a queue, and the broker sends again, but only after connecting again (blue arrow))
This implies that if no re-connection happens, we may never get a retry of the queued messages.
(sorry for multiple replies, the system is not letting me post all screenshots at once)

Will check and come back to you :slight_smile:

Hi,

With TCP you can expect that your packets arrive exactly in the order that you sent them, or not at all. If the packets ultimately do not arrive then the connection is considered to have dropped, and a new connection is required. There is no scenario with TCP where some packets go missing but the connection has not restarted.

In MQTT v3.1.1 retrying message delivery during a session was allowed, however it is a fundamentally bad idea to implement this. The reason is this - if you have a reliable network connection, the only way that a client/broker will not respond to a PUBLISH by sending a PUBACK is if it is unable to do so. This may mean that the client/broker is overloaded. In this case, retrying the message will make the situation worse. If the client/broker is not overloaded but has not replied for another reason, perhaps waiting on the message to be processed in some way the same is true. Sending a message retry will just add further load to the system.

The other scenario is that the network connection is unreliable. This gives two situations - either the unreliable situation is short lived and the connection is recovered without loss, or the connection completely drops. In the first case, when the connection recovers the TCP stack of the sender must ensure that the outgoing packets remain in the exact order they were given to it by the application. As far as the client is concerned, there was just some extra latency in the connection. Sending a message retry in this case achieves nothing except for wasting bandwidth and adding extra load. Where the network connection drops completely, the case is clear - we need to make a new TCP connection and start a new MQTT session, which means sending first a CONNECT - and then we must retry our outgoing messages.

I hope this makes it clear that doing in-session retries is actually counterproductive.

Regards,

Roger