Handling backpressure data tranmission in mqtt client - mqtt

We have a mosquito broker installed in our cloud server. Our gateway is sending data by using an MQTT client with 2G signal. We are observing data loss in a few scenarios.
When the gateway is disconnected from internet we queue messages in the gateway for few days. When it reaches the internet again then it starts pushing data to broker with two threads: one is for live messages, the other is for queued messages. We get a callback ACK for each and every message but we are loosing some messages on the server side.
How do we make sure that all produced messages will be processed in the broker?
How do we handle the burst of message in the gateway? One option is to delay the sending of each queued message by a few milliseconds (to avoid that they all try to reach the broker at once.
We are using QoS level 1 for our publisher/subscriber and want to continued using QoS level 1.

Related

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

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
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.

Rollback Feature in MQTT Broker after message received from Broker

I have a Situation once message received from MQTT Broker, During processing the data , assume that DB is down and not completed the task. In that particular situation Data that received has to sent back to Broker that my task is not completed I mean rollback.
How to achieve this and how to tell broker that during processing the data some exception came and you need to send the data again.
can some one hep on this?
It can be done, but only with certain MQTT client libraries that allow you to take full control of the QOS handshake process.
Assuming a client has subscribed at QOS 1 or 2 to a topic it can then chose to hold of sending the PUBACK or PUBREC packet back to the broker. It can hold off completing the QOS handshake until the message has been fully processed. If the processing fails and the full handshake is not completed then the broker will try to redeliver the message again to the client so the client should go offline in the case of a failure so the broke will queue the message.
When the backend (datastore) comes back online the client can reconnect to the broker and the queued messages will be redelivered.

Increase MQTT Time between PUBLISH and PUBCOMP

I have configured a MQTT subscriber in spring using spring mqtt integration. In the handleMessage method I am doing certain business logic which takes time. While testing I noticed that when I am sending bulk number of messages the Broker republishes the same message as an original message (I checked whether the Message payload is duplicate , it was sending as original). The MQTT Broker is publishing the message again even before the Subscriber can send PUCOMP. QOS level is set to 2
You should not be doing long running tasks in the handleMessage callback as this is run on the MQTT Clients network thread.
If you have a long running task you should be handing it off to a separate thread pool to run.

Rebooting server with MQTT service

Imagine an MQTT broker with remote clients connected, which continuously send QoS 2 data - the standard situation. Clients are configured with "cleansession false" - they have a queue to send messages in case of a connection failure.
On the server, local clients subscribe to topics to receive messages.
Server load:
Launch the MQTT Broker
Running local clients
Connecting remote clients and receiving data from the queue
What if the third point occurs before the second? Are there standard solutions? How not to lose the first messages?
Assuming you are talking about all later reboots of the broker, not the very first time the system is started up then the broker should have stored the persistent subscription state of the clients to disk before it was shutdown and restored this when it restarted. This means that it should queue messages for the local clients.
Also you can always use a firewall to stop the remote client being able to connect until all the local clients have started, this would solve the very first startup issue as well.

Unable to receive all published messages [AWS IOT]

I'm trying to publish 1000 messages per second using 5 processes with 200 messages each on a unique topic. And trying to listen using 5 processes each one listening on one topic on which messages are being published.
The problem is I'm unable to receive all the thousand messages and the number of messages received is not constant every time I follow this process.
As far as I understood AWS IOT should be allowing 3000 inbound messages per second.
Try to publish data at QOS-1 or QOS-2 level.
What is Quality of Service?
The Quality of Service (QoS) level is an agreement between sender and receiver of a message regarding the guarantees of delivering a message. There are 3 QoS levels in MQTT:
At most once (0)
At least once (1)
Exactly once (2).
When talking about QoS there are always two different parts of delivering a message: publishing client to broker and broker to subscribing client. We need to look at them separately since there are subtle differences. The QoS level for publishing client to broker is depending on the QoS level the client sets for the particular message. When the broker transfers a message to a subscribing client it uses the QoS of the subscription made by the client earlier. That means, QoS guarantees can get downgraded for a particular receiving client if subscribed with a lower QoS.
Why is Quality of Service important?
QoS is a major feature of MQTT, it makes communication in unreliable networks a lot easier because the protocol handles retransmission and guarantees the delivery of the message, regardless how unreliable the underlying transport is. Also it empowers a client to choose the QoS level depending on its network reliability and application logic.

Resources