MQTT 3.1.1 broker QoS=1 ("at least once") message redelivery

1.9k views Asked by At

I am trying to find out the reality about MQTT 3.1.1 message re-delivery for messages received by a MQTT subscriber with "at least once" (QoS 1) configuration:

  • Do MQTT brokers re-deliver un-acknowledged "QoS 1" messages from subscribers?
  • How much time must pass until MQTT broker re-deliver?
  • Does the MQTT broker try endlessly to re-deliver an unacknowledged message?
  • Are there other ways to trigger a re-delivery?

Assuming that a MQTT subscriber does not respond with a PUBACK message to a received MQTT message, the MQTT broker needs (at least from my understanding) re-deliver the message which must be received "at least once" until the subscriber sends a PUBACK for that message.

To get more concrete on what I am trying to achieve:
Is it a good/valid idea to postpone sending the PUBACK until a received message was successfully persisted - effectively enlarging the QoS level until my subscribing application guaranteed that the message was processed.
And whether for e.g. persistence errors (timeouts to the database) no PUBACK would be send which would automatically result in a re-delivery of such messages.

Thx & best regards

1

There are 1 answers

1
Brits On BEST ANSWER

Do MQTT brokers re-deliver un-acknowledged "QoS 1" messages from subscribers?

From [the spec]:

When a Client reconnects with CleanSession set to 0, both the Client and Server MUST re-send any unacknowledged PUBLISH Packets (where QoS > 0) and PUBREL Packets using their original Packet Identifiers [MQTT-4.4.0-1]. This is the only circumstance where a Client or Server is REQUIRED to redeliver messages.

So, yes, unacknowledged QOS1 messages will be redelivered but the only time the spec REQUIRES this to happen is when a client reconnects.

While you specificity state you are using MQTT v3.1.1 I believe it is worth noting that MQTT v5 expressly prohibits re-delivery other than following a reconnect:

When a Client reconnects with Clean Start set to 0 and a session is present, both the Client and Server MUST resend any unacknowledged PUBLISH packets (where QoS > 0) and PUBREL packets using their original Packet Identifiers. This is the only circumstance where a Client or Server is REQUIRED to resend messages. Clients and Servers MUST NOT resend messages at any other time

How much time must pass until MQTT broker re-deliver?

As per the above automatic retry is not required by the spec. Some brokers may retransmit after a period of time. emqx supports this; mosquitto used to have an option but this was removed in version 1.5 with the change log explaining:.

Outgoing messages with QoS>1 are no longer retried after a timeout period. Messages will be retried when a client reconnects. This change in behaviour can be justified by considering when the timeout may have occurred.

  • If a connection is unreliable and has dropped, but without one end noticing, the messages will be retried on reconnection. Sending additional PUBLISH or PUBREL would not have changed anything.
  • If a client is overloaded/unable to respond/has a slow connection then sending additional PUBLISH or PUBREL would not help the client catch up. Once the backlog has cleared the client will respond. If it is not able to catch up, sending additional duplicates would not help either

Does the MQTT broker try endlessly to re-deliver an unacknowledged message?

The 3.11 spec does not provide any guidance (so, in theory, yes) but many brokers provide some control over this (maximum number of messages queued, max size of queue etc).

Are there other ways to trigger a re-delivery?

Yes - disconnect and reconnect.

Is it a good/valid idea to postpone sending the PUBACK until a received message was successfully persisted

There was a discussion re this on the paho-dev group a couple of months ago. Its something that is being considered in the Go v5 Client (currently that client automatically acknowledges messages).

One thing to note is that the MQTT spec does have requirements with regards to the order acknowledgments are sent. Many clients ignore this requirement (and just send the acknowledgments whenever the handler returns) but some (e.g. the HiveMQ Java client) queue up ACKs so they can be sent in the correct order.