13 March, 2019

Sticky shared subscriptions — smarter load balancing with flespi MQTT broker

Control the randomness of your MQTT load balancing.

flespi MQTT broker is a superstar in the world of High Load tasks and load balancing capabilities... 

flespi mqtt sticky shared subscriptions

But seriously, the more high-load system you have, the higher the probability of problems. Thus, you need more special tunings and management tools to keep everything under control.

How to manage a random process?

In a classic load balancing case, workers receive messages from the broker randomly. But in some cases, you may need to be in charge of this “randomness”. Consider the most common example of a high-load system with many publishers and a small number of workers subscribed with a shared subscription:

classic mqtt load balancing

What we see here is that each worker can process messages from each publisher, thus a worker needs to store cache data for all publishers. Messages are randomly distributed between workers.

Following is the example showing the advantage of sticky subscriptions:

mqtt load balancing with sticky subscriptions

Each worker is responsible only for the publishers that are randomly assigned to it. So there is no need to store cache for all publishers.

It’s important to note that this situation takes place as soon as the system gets stabilized: a constant number of publishers and a constant number of workers. What will happen if the system gets disrupted?

Well, a new worker can pull some publishers from old workers and have new publishers associated with it. However, migration of publishers between old workers is not possible. Conclusion: adding a new worker to the system may only load off old workers.

mqtt load balancing disrupted system

How does it work? 

Shared subscription is tied to the topic. Sticky shared subscription must use some attribute to know which worker to use as a target. This attribute may only be part of the topic. You tell the broker which part of the topic to use for sticky subscription and the broker generates a hash of this topic substring and uses it to dispatch the messages.

There are 2 ways to set up sticky shared subscriptions.

  1. $share/name:count where count is the length of the topic section from the beginning to calculate the topic hash. E.g. if you want to implement manageable load balancing for channel messages subscription – flespi/message/gw/channels/{channel_id}/{ident}

    $share/by_ident:6/flespi/message/gw/channels/+/+ channel messages from the device with certain ident will be delivered to one stable worker.
  2. $share/name:from:count where from is the position of the starting word (counting from zero) of the substring to be used for topic hash calculation. E.g. if you want to implement manageable load balancing for device messages, telemetry, state etc., you use the following subscription $share/by_device_id:4:1/flespi/+/gw/devices/+/# (use only 5th word for hash calculation)

    Upon this subscription you will receive messages for topics:
    flespi/state/gw/devices/{device_id}/telemetry/{parameter}
    flespi/message/gw/devices/{device_id}
    flespi/state/gw/devices/{device_id}/settings/{name}

    And messages for certain device ID will be processed by the same worker.

Conclusion

Sticky subscriptions feature is an extension of the MQTT standard: it is not described in MQTT specification but it does not violate it. So it’s unlikely you will find it in other brokers. But flespi is OK with the role of a trend-setter in the MQTT broker community — if the concept gets accepted by the users, other brokers might want to implement it. Maybe we’ll even see it as a part of MQTT 6.0…;)