Monday, March 27, 2017

MQTT - Persistent and Clean Sessions

The persistent session feature of MQTT allows the broker to save the following information about a client:

  1. All topics that it to which it subscribed, along with the QoS level for each
  2. All unconfirmed QoS 1 or 2 messages sent to those topic(s)
  3. All new QoS 1 or 2 messages sent to those topic(s) while the client is offline

Since we have been using mosquitto_sub, we are only able to subscribe to a single topic. In real applications, subscribing to multiple topics is a real possibility. Using a persistent session saves us from having to resubscribe when a client disconnects then reconnects. Having any missing QoS 1 or 2 messages resent is also a good thing!

When mosquitto_sub connects to a broker, by default it creates what is called a clean session, which means that the subscription(s) have to be created from scratch, and it doesn't get unconfirmed or new QoS 1 or 2 messages sent while the client was offline.

To create a persistent connection using mosquitto_sub we must:

  1. specify a client ID using the -i flag
  2. disable clean session by adding the -c flag
  3. use a QoS level of 1 or 2 using the -q flag.

When a client connects using a persistent connection, it is called a durable client.

To see how all this works, we create three windows:
Window #1: mosquitto -v
Window #2: mosquitto_sub -d -h localhost -i Subscriber1 -c -q 1 -t home/living-room/temperature

Because we used the -c flag, specified a clientID (Subscriber1), and set the QoS level to 1, the broker has created a persistent session for this client.

Now press CTRL-C in Window #2 to stop the subscriber.

Next, we publish some messages to the topic home/living-room/temperature in Window #3:

mosquitto_pub -d -h localhost -t home/living-room/temperature -q 1 -m "Message 1"
mosquitto_pub -d -h localhost -t home/living-room/temperature -q 2 -m "Message 2"
mosquitto_pub -d -h localhost -t home/living-room/temperature -q 1 -m "Message 3"

Now back in Window #2, we restart the client using the same command as above:

mosquitto_sub -d -h localhost -i Subscriber1 -c -t home/living-room/temperature

What we see is that Subscriber1 receives the three messages that it missed:

pi@raspberrypi:~ $ mosquitto_sub -d -h localhost -i Subscriber1 -c -q 1 -t home/living-room/temperature
Client Subscriber1 sending CONNECT
Client Subscriber1 received CONNACK
Client Subscriber1 sending SUBSCRIBE (Mid: 1, Topic: home/living-room/temperature, QoS: 1)
Client Subscriber1 received PUBLISH (d0, q1, r0, m4, 'home/living-room/temperature', ... (9 bytes))
Client Subscriber1 sending PUBACK (Mid: 4)
Message 1
Client Subscriber1 received PUBLISH (d0, q1, r0, m5, 'home/living-room/temperature', ... (9 bytes))
Client Subscriber1 sending PUBACK (Mid: 5)
Message 2
Client Subscriber1 received PUBLISH (d0, q1, r0, m6, 'home/living-room/temperature', ... (9 bytes))
Client Subscriber1 sending PUBACK (Mid: 6)
Message 3

Since Subscriber1 connected to the topic using QoS 1, "Message 2" (which was sent with QoS 2) will be received as QoS 1.

In all fairness, this is not a true test of persistent sessions, because mosquitto_sub requires that we specify a topic. Were we to use another client, we wouldn't have to resubscribe to that topic.

Note that this is the first real "queue" we have seen in MQTT.

By default, Mosquitto will save persistent session information in memory, not to disk. Further, the sessions NEVER expire by default. This can be changed by modifying mosquitto.conf.

3 comments: