How to enforce the order of messages sent to the IoT device via MQTT using the cloud system (API design problem)

Suppose I have an IoT device that I am going to monitor (say, turn on / off) and monitor (for example, collect temperature readings). It seems MQTT may be appropriate. I could publish messages on the device to control it, and the device could publish messages to the broker to report temperature readings. So far so good.

Problems arise when I try to create an API for device management.

The day is coming when the device subscribes to two questions:

  • / identifier device / control / on
  • / identifier device / control / off

Then I post on these topics in some order. But given the fact that messaging is usually an asynchronous process, there are no guarantees regarding the order of messages received by the device.

So, if two posts are published in the following order:

  • / identifier device / control / on
  • / identifier device / control / off

they can be taken in reverse order, leaving the device turned on, which can have dramatic consequences depending on the context.

Of course, the API could be designed in some other way, for example, there can only be one topic

  • / device identifier / management

and the payload of the individual messages will be the value of the individual message (on / off). Therefore, if you publish messages in this section in a certain order, they are expected to be received in the same order on the device.

But what if the publication order of individual topics cannot be guaranteed? Assume the following system architecture for IoT devices:

/ control service \ application -> broker -> control service -> broker -> IoT device \ control service / 

System Components:

  • an application that effectively controls the device by publishing messages to the broker
  • typical message broker
  • management service with some business logic

The important role is that, as in most modern distributed systems, the management service is a distributed multi-instance object that can simultaneously process several management applications from an application. Therefore, the order of messages published by the application can be completely mixed when delivered to the IoT device.

Now, given the fact that most MQTT brokerage companies sell only QoS0 and QoS1, but QoS2 it becomes even more interesting, since such control messages can be delivered several times (provided that QoS1 - see https://stackoverflow.com/a/3129648/) / ... ).

My point is that separate topics for control messages are a bad idea. The same goes for one topic. In both cases, there is no guarantee of message delivery.

The only solution to this particular problem that comes to my mind is message versioning, so old (obsolete) messages can simply be skipped when delivered after another message with a more recent version property.

  • Did I miss something?
  • Is the post version the only solution to this problem?
+6
source share
3 answers

Did I miss something?

Most definitely. The example you cited is a general management system tied to some message-oriented scheme. There are several patterns that you can use when referring to a message-based architecture. In this article, Microsoft classifies message templates into two primary classes:

  • Teams and
  • Developments

The most common command behavior pattern is issuing a command, and then measuring the state of the system to verify that the command has been executed. If you forget to check, your system has an open circuit. Such open loops (unfortunately) are common in IT systems (because they are easy to forget), and often lead to errors and other bad behaviors, such as those described above. So, the correct way to process the command is:

  • Run the command
  • Request system status
  • Rate next action

Events, on the other hand, simply fire. As an event publisher, my business is not to worry about who receives the event, in what order, etc. Now you must also indicate that the use of any decent message broker (for example, RabbitMQ ), as a rule, bears strong guarantees that the messages will be delivered in the order in which they were originally published. Please note that this does not mean that they will be processed in order.

So, if you consider a team as an event, your system will usually act sooner or later.

Is the message version the only solution to this problem?

Message versioning usually refers to a property of the message class itself, and not to a specific instance of the class. It is often used when there are multiple versions of the message-based API and must be backward compatible with each other.

What you call instead are unique message identifiers. Guids especially convenient for ensuring that each message receives its own unique identifier. However, I would say that deduplication in a message-based architecture is an anti-pattern. One of the consequences of using messaging is that duplicates are possible, so you should try to create stateless and idempotent behavior on your system. If this is not possible, keep in mind that messaging may not be the right communication solution for this need.

As an example, using the command-event dichotomy, you can perform the following transaction:

  • The controller issues a command, assigning it a unique identifier.
  • The control system receives a command and turns on.
  • The control system publishes a notification about the event "lights up" containing a unique identifier for the command that was used to turn on the light.
  • The controller receives a notification and maps it to the original command.

If the controller does not receive notifications after some timeout, the controller can re-execute the command. Note that "light on" is an idempotent command in which multiple calls to it will have the same effect.

+4
source

When the state changes, immediately send a new state, and then periodically every x seconds. Thanks to this solution, your systems get to the desired state after a while, even when it is temporarily disconnected from the network (low battery).

By the way: You did not miss anything.

+1
source

In addition to the comment that most brokers do not support QOS2 (I suspect that you mean that some brokers do not support QOS2 as service offers, for example, Amazon AWS IoT), you covered most of the main points.

If the message is really really important, then you will need to indicate some form of order marker in the message payload, whether it is a counter or a timestamp.

+1
source

All Articles