Who sends pings in MQTT? - mqtt

The keepalive feature in MQTT helps detecting connection problems. That is, if the broker has not received any data from the client in 1.5 * keepalive seconds, it considers the client disconnected. But who should send periodic pings when keepalive is enabled? Broker or client?
The MQTT standard at http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc385349238 states that the client must send PINGREQ packets if it has no other data to send.
On another hand, mosquitto_connect() function of libmosquitto (https://mosquitto.org/api/files/mosquitto-h.html#mosquitto_connect) has the following description of keepalive parameter:
keepalive: the number of seconds after which the broker should send a PING message to the client if no other messages have been exchanged in that time.
I wanted to clear up this confusion. I lean towards the variant from MQTT standard, but would like to know for sure. Also maybe this indicates a bug in libmosquitto implementation?
Specifically, I use libmosquitto version 1.6.12.

I think this is a bug in documentation of libmosquitto.
The MQTT standard does not specify a way for the broker to initiate ping messages, only to respond to them. The implementation in libmosquitto client library appears to use the keepalive parameter for periodically sending packets to the broker, just like the standard specifies.
So it seems the documentation should read:
keepalive: the number of seconds after which the client should send a PING message to the broker if no other messages have been exchanged in that time.

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.

client <clientname> has exceeded timeout disconnecting

I am using MQTT 3.1.1, I have installed a mosquito as a local server on my computer.
I am sending the Some sensors data from pubsubclient (MQTT client library ) to the mosquito and saving it to the database from the mosquito server
Whenever I start the session upto 5-10 minutes I am getting the messages but after that
MQTT client couldn't send any message and disconnect automatically.
Before disconnecting it prints the following message in command line
client <clientname> has exceeded timeout, disconnecting
Socket error on client <clientname>, disconnecting.
Also I am using the server with default configurations, except the QOS is set to 2
What is causing this error and
What should I do, so that client should not disconnect from my local server ?
The node(s) that is(are) Subscribing (and maybe the Publishing nodes if they take too long to Publish again) need the 'keepalive' field on the Connect call set. Most MQTT Brokers will timeout connections after something like 5 minutes, unless you have modified the timeout value in the settings.
Set the 'keepalive' option to something like 30 or 60 seconds will prevent the MQTT Broker from disconnecting. You Subscribers will start sending PINGREQ packets, and the MQTT Broker will reply with PINGRESP packets.
Read more here: http://www.steves-internet-guide.com/mqtt-keep-alive-by-example/

MQTT - listen to ping, disconnect and connect events

I have "server side" mqtt client which I use to monitor and manage remote mqtt clients. I would like to extend this server module to keep tabs on the connectivity of the remote clients.
During normal operation, the remote clients regularly PING the broker, as per the broker logs:
1532924170: Received PINGREQ from c51
1532924170: Sending PINGRESP to c51
and when a disconnection occurs, the broker logs show this too:
1532924976: Client c51 has exceeded timeout, disconnecting.
1532924976: Socket error on client c51, disconnecting.
as well as the subsequent re-connection:
1532924978: New client connected from X.X.X.X as c51 (c1, k30).
1532924978: Sending CONNACK to c51 (0, 0)
I would like to monitor these 3 events from the mqtt-client held by the server module. Is this possible? If not, what alternative approach to "health" monitoring can you recommend?
No, you can not read these from a connected client.
The only pure MQTT approach is to make use of the Last Will and Testament (LWT) feature. You have the client set up a LWT publish a retained message to a client specific topic that marks it as offline. Then as the client connects it should publish a retained message to show you are online. If you disconnect cleanly (not triggered by keep alive time out you should manually publish the LWT message as the last thing before disconnecting).
It's also worth pointing out that ping messages only get sent if no other messages have been sent between the client and the broker in the keep alive period.

Handling backpressure data tranmission in mqtt client

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.

MQTT broker communication to MQTT Client

I already have a cumulocity client that communicates with the cumulocity broker through MQTT.
What should I do in order to send data back from MQTT broken in cumulocity to mqtt client? (Say the client sends some data and I want the confirmation that the data was sent successfully)
For some reason couldn't find any info on this on the cumulocity docs the only for client.
If you want to get confirmation from the server of getting your data you should use the normal MQTT QoS. http://cumulocity.com/guides/mqtt/implementation/
If you want to send data in general from the platform to your device client operations is what you are looking for. This is currently the only data you can subscribe to on Cumulocity MQTT.
http://cumulocity.com/guides/concepts/domain-model/#operations
You can check the python example. It contains the subscription part
http://cumulocity.com/guides/mqtt/hello-mqtt-python/
You should connect to the broker with Qos 1 or above. This will guarantee that the data has reached the broker at least once. The client will be receiving the PUBACK message once this happens. If the connectivity is lost then the client is supposed to re-send the PUBLISH message with Duplicate flag set. So the cient should stop publishing when a PUBACK is received.
For more information about Qos, refer this link
HiveMQ/blog/mqtt-essentials/QualityOfService

Resources