
MQTT: An Implementer's Perspective - jstclair
http://vasters.com/clemensv/2014/06/02/MQTT+An+Implementers+Perspective.aspx
======
eldavido
I've been working on a project to do building monitoring. I'm building a
library in C that talks to an Akka/Scala backend.

I initially chose MQTT to connect from the C library (that runs on the device)
to the Akka system, via RabbitMQ's support for MQTT.

As I get deeper into the implementation, I'm thinking about ripping out MQTT.
I just don't know what purpose it has. I think a better pattern is to have
some kind of TCP terminator that the client/device connects to, which then
fans out into an AMQP-like messaging system. Pushing messaging away from the
core, far towards the edge doesn't seem like a good idea in environments where
you really care about whether something is up/connected, and also, the wire
protocol you use from the cloud to your device can be a lot different from
that which you'd use in a core/cloud/racked messaging system.

I also don't care for MQTT's security model.

All in all, I'm pretty disappointed with it as a protocol. I'd take something
written in protobuf and well-documented any day over mqtt.

My project, in case anyone's interested:
[https://github.com/prefiat/iotelemetri-
feederd](https://github.com/prefiat/iotelemetri-feederd)

------
jandrewrogers
This write up is right on the mark. There are quite a few things about MQTT
that seem to have the goal of supporting legacy expediency. At the same time,
these dubious design elements undermine the nominal goals of the standard and
in some cases flat out contradict those goals.

We know how to design modern, efficient, flexible wire protocols that can be
driven at the rates required by M2M communication patterns. MQTT does not fit
this description nor even makes an attempt to reflect best practices within
its current scope.

~~~
tkellogg
For the life of me I can't find anywhere that says "extensibility" is a goal
of MQTT. The main goals are clearly stated to be "simplicity" and
"lightweight". Extensibility is the enemy of both. A lot of Clemens' points
are based on the concept that MQTT is supposed to be extensible. When you
realize that's not even a goal, most of his concerns become moot. He says "I'm
not trying to create another AMQP" but if you think about what he's actually
saying, it's quite the opposite.

~~~
clemensv
There are not many modern app-level protocols and much fewer messaging
protocols that don't allow for any end-to-end message metadata; at a minimum
declaring what the payload content of a message is, when the message was
generated, and an end-to-end ID. Content-type could be a mere byte the client
sends to the app and where 0x01 spells "JSON". CONNECT shows how you can have
a bitfield that can control the presence of headers. You can control the
presence of 4 subsequent optional headers with 4 shape options in one byte.
That's as simple as what happens in CONNECT and just as compact.

There are also not many modern app-level protocols that constrain their
opcode-set to 4 bits quasi forever, so extensibility also means to have runway
for future extension.

~~~
dragonwriter
> There are not many modern app-level protocols and much fewer messaging
> protocols that don't allow for any end-to-end message metadata; at a minimum
> declaring what the payload content of a message is, when the message was
> generated, and an end-to-end ID. Content-type could be a mere byte the
> client sends to the app and where 0x01 spells "JSON".

Sure, and suddenly you're limited to 256 content types, or, more likely,
burning an extra byte and _still_ frequently needing to communicate the actual
substantive content-type in the payload. If you are going to bother having
content-type be part of the messaging protocol, do it _right_ rather than by
half-measures.

As I see it, there's a continuum of messaging protocols from barebones
(requiring smarter components) to full featured (that require the components
to do less because the protocol and broker do more). ØMQ sits close to the
first extreme -- call it "the left" \-- and AMQP pretty close to what would
then be "the right" (at least, the closest of any current open protocol that I
am aware of); MQTT seems to be just to the right of ØMQ (I mean, it _has_ a
broker).

------
jhallenworld
He says:

"Unfortunately, MQTT defines this assurance model only for the publish gesture
and not for its own, inherent operations.."

OK, but then says:

"That means the client is forced to retry under any such circumstances. The
specification already anticipates this with making subscriptions effectively
idempotent and requiring that a subscribe command matching an existing
subscription must be replaced by a new subscription and that the message flow
must not be interrupted. "

So what exactly is the problem? If the client doesn't get the SUBACK it
retries. The server has to deal with it. If the server gets a SUBSCRIBE, it
has to be durable because the client might have received the previous SUBACK.

Why add one more turn around by acking the ack? This seems like extra
complexity for no reason.

Also he talks about lack of flow control:

"Not having any flow control can get fairly dicey when there is significant
work to do for processing a message and there might be several different
subsystems on the receiving end of the MQTT connection where the work
differs."

But there is flow control: it's TCP. Do not read from the TCP stack unless you
can handle the message, then the flow control will work. On the other hand
there is no concept of trying to multiplex multiple streams over one
connection (where then you start to worry about head of line blocking). If you
need this, open a different TCP connection for each stream. This is not an
unreasonable design choice to make...

~~~
Groxx
How do you know if you can handle the message, until you read the message? Or
is MQTT's flow control inherently insufficient for cases like that?

Basic example, say for a chat client: to ensure delivery, you probably want to
read the message, save it to a database, _then_ confirm receipt. Is that
possible, or would that delayed-ack have to be done via some other means?

~~~
jhallenworld
That's the normal use case for QoS 1 and 2 messages: the client must
acknowledge each received message otherwise the server will try to resend it.
From the MQTT V3.1 Protocol Spec:
[http://public.dhe.ibm.com/software/dw/webservices/ws-
mqtt/mq...](http://public.dhe.ibm.com/software/dw/webservices/ws-
mqtt/mqtt-v3r1.html#retry)

What you don't want to do is read everything offered into memory faster than
you can write it to disk / database. You could potentially fill the memory
until you run out and crash. Instead control the flow by not reading until you
are finished with the previous message (or better, allow N unacknowledged
messages to be read, where N is just enough so that the application is as fast
as it can be).

------
Bug_Labs
Great write up! We found many of the same issues as you did when we tried
connecting devices, so we created dweet.io.

We are not a substitute for MQTT, but we made dweet to help you get your
things online quickly and easily so you can concentrate on making apps.
Standards take forever to hash out, so we made something that can get you
going really quickly.

Have you had a chance to look into dweet? [https://dweet.io](https://dweet.io)
is the homepage, so let me know if you have any questions.

Thank you again

~~~
secoif
This comment's sales pitch tone really comes to a crescendo around "Have you
had a chance to look into dweet?", just FYI you may want to avoid this type of
language in the future.

~~~
HeyLaughingBoy
So what's wrong with that? He built a service and he's suggesting that someone
who might have an interest take a look at it.

"Build stuff, tell people about it."

------
tobinharris
We selected MQTT because our mobile apps are sending frequent data packets
over cell-phone data tariffs. Our thinking was that a light messaging protocol
such as MQTT could mean the difference between an £100,000+ monthly data bill,
or £10,000.

I'm no expert, but I'm finding MQTT pretty bare bones, I can see the appeal of
STOMP or messaging protocols that have more support for patterns such as RPC.

------
outside1234
I'm so glad this was published because I had essentially come to the same
result and thought I was missing something given all the hype around MQTT.

------
rdtsc
Btw there is a RabbitMQ plugin that does MQTT

[http://www.rabbitmq.com/mqtt.html](http://www.rabbitmq.com/mqtt.html)

------
jallmann
What an extremely well thought-out piece. There is a certain bias towards
MQTT’s suitability for building Azure-scale services (the article says as
much), but I just wanted comment on a few general points.

> you cannot return connack (which confirms establishing or recovering a
> session) until all server nodes have access to a replica of this fact. The
> spec doesn't say that.

The spec should not have to say that. If you're building high-availability,
distributed _brokers_ (which MQTT makes no claims about), the semantic
implications of each message should certainly be considered carefully, but a
protocol specification is not a "how-to" guide enumerating every use-case. A
brief note calling into consideration special cases may be welcome, but should
not be required.

> With a "pull" based model that separates establishing subscriptions and
> message solicitation, you can leave delivery resumption control to the
> client, with MQTT those two aspects are coupled.

This behavior is a non-issue if the clear session flag is set. If it's not
being set, the assumption is that subscription state is actively managed by
the server. Leaving more work to the client is half-hearted and would
complicate the protocol into something like AMQP’s. (I have thoughts about
whether pull models are best suited for stateless operation, but that’s
neither here nor there.)

Client IDs are indeed mis-named. To be fair, the 3.1.1 spec allows for server-
assigned client ids. That doesn't completely mitigate the security risk, as
user credentials are allowed to be shared among endpoints. This can be “fixed”
at the broker level by requiring unique credentials, depending on the use case
— it likely wouldn’t work for Azure.

The objection to the (lack of a) payload encoding is unclear. Being payload-
agnostic actually a nice feature, especially on the broker side. Crucially —
and please correct me if I'm wrong — MQTT is not designed as a generic
mechanism to communicate with unknown clients, vis-a-vis HTTP. Clients are
assumed to have awareness of the payload structure. Metadata can be further
signified via a structured topic (again, clients know the format of the
topic).

The article calls the structured-topic approach a hack, but it is a easy,
readable method to impose simple structure or namespacing, and allows for
things like metadata-based routing without any special effort from the broker.
Hence, the need for explicit metadata (content-type, etc) seems unnecessary.

Regarding flow control — unless the spec declares otherwise, the broker is
free to implement specific policies regarding the number of in-flight
messages. For example, Mosquitto handles ACLs out-of-band. Otherwise, you can
rely on TCP buffers to limit in-flight messages, or delay a QoS response until
the next message can be handled. This also applies to data management
policies, e.g. state or message retention, QoS-2 allowances, and so forth.
Spec ambiguity is not necessarily a bad thing here. Over-specifying could
constrain other use-cases; the insistence on “watertight assurances” doesn’t
always hold water.

Multiplexing is not really an issue, unless you are sending large payloads —
although if you are, I would venture to say you’re not using the right
protocol anyway. I will place fault with the protocol for allowing 256MB
payloads — this really just goes to show the incongruity between MQTT’s
frugality with headers and wastefulness everywhere else.

All this assumes the user is using MQTT as it was designed: for _simple_ pub-
sub. What it allows out-of-the-box may not be flexible enough for many use
cases. These problems can be mostly fixed with small changes to the protocol,
or fixating on certain assumptions. This usually necessitates
writing/modifying your own broker, but fortunately MQTT is simple enough that
it isn’t a heroic deed. Of course, this doesn’t apply if you’re building a
SaaS broker like Azure — but for any other purpose, MQTT can be viewed as a
springboard.

Granted, all this sounds like it requires thinking too much about details that
should otherwise be solved by things like AMQP. Maybe so. However, more
sophisticated systems have many more knobs to tune, and the complexity rises
accordingly. MQTT doesn’t have that problem out-of-the-box.

