Web Design

Your content goes here. Edit or remove this text inline.

Logo Design

Your content goes here. Edit or remove this text inline.

Web Development

Your content goes here. Edit or remove this text inline.

White Labeling

Your content goes here. Edit or remove this text inline.

VIEW ALL SERVICES 

Discussion – 

0

What do message queue protocols actually guarantee?

In the previous article, we separated the communication model, point-to-point or publish-and-subscribe, from what actually travels between producer and consumer. This article goes one layer down, into message queue protocols, and starts from a problem that shows up in practice: a team picks a protocol because its client library is easy, assumes “guaranteed delivery” comes with it, and learns after a broker restart that the protocol never promised to keep anything. Send a message to Apache ActiveMQ over STOMP without the persistent:true header and it is not saved: ActiveMQ’s STOMP documentation states that STOMP messages are non-persistent by default.

A message queue protocol is the wire contract between an application and a messaging system: which frames exist, what an acknowledgment means, and which promises a client is allowed to ask for. That is also why JMS is not on the list below: it is a Java API, and says nothing about what travels on the wire.

Matrix of five message queue protocols, AMQP, MQTT, STOMP, XMPP and OpenWire, against six messaging properties, with the clustering column highlighted
No protocol defines clustering; that is always the broker’s job.

Six properties every messaging system is judged on

Luca Magnoni, at CERN, summarized the features that messaging systems share in Modern messaging for distributed systems (ACAT 2014). We use six of them as the test; his list also names high availability, which we fold into clustering.

  • Persistence: the message is saved to disk or a database, so a restart does not lose it.
  • Failover: clients reconnect automatically when a broker fails.
  • Guaranteed delivery: the delivery policy, from at most once to exactly once.
  • Ordering: messages arrive in the order they were produced.
  • Transactions: several operations commit or roll back as one.
  • Clustering: brokers form a network for high availability and load balancing.

He adds the caveat that matters most here: the main brokers share these features, but interpret them differently.

Message queue protocols state promises; brokers keep them

That caveat is the key to reading any comparison of message queue protocols. A protocol can do one of three things with a property:

  • Define it: the wire carries the promise, and both ends must honor it.
  • Leave it partly to others: the protocol carries a signal, an extension adds the feature, or the broker decides.
  • Not address it: the property is entirely the broker’s business.

Persistence and clustering live mostly in the broker. Delivery guarantees and transactions are where protocols differ most, because they are about what the two ends agree on the wire. The five below are AMQP and the open protocols commonly listed beside it.

AMQP 1.0: the contract written down

AMQP 1.0 is an OASIS standard built so that independent implementations interoperate. The protocol is symmetric: at the wire level, it does not even distinguish clients from brokers.

  • Persistence: defined. A message marked durable “MUST NOT be lost even if an intermediary is unexpectedly terminated and restarted”, and a target that cannot honor this must refuse the message (Messaging, section 3.2.1).
  • Failover: partial. Link state can outlive the connection, so a link can be resumed with its unsettled deliveries (Transport, section 2.6). Choosing another server is left to the client library.
  • Guaranteed delivery: defined. Each delivery is settled or unsettled, and the state kept at both ends allows precise control, up to exactly once. Implementations may stop short: Azure Service Bus supports at least once and offers duplicate detection instead.
  • Ordering: partial. Transfers are numbered within a session, but the messaging layer makes no general ordering promise; a higher priority may legitimately overtake.
  • Transactions: defined. Part 4 groups transfers across any number of links into one outcome, committed or rolled back on discharge. Distributed transactions are deferred to a separate specification.
  • Clustering: not addressed.

The architecture explains the result. A standard meant for many vendors writes down what two ends must agree on, delivery, durability and transactions, and leaves out what depends on how a broker is built.

MQTT: delivery levels sized for a sensor

MQTT was designed for low-bandwidth, high-latency networks, and its specification (3.1.1, 5.0) defines exactly what a device on such a network needs.

  • Persistence: partial. With a persistent session, the server must store QoS 1 and QoS 2 messages for a disconnected client, and retained messages are kept for future subscribers. How they are stored is the broker’s choice.
  • Failover: partial. MQTT 5 lets a server send a client elsewhere, with the reason codes “Use another server” and “Server moved” and a Server Reference property. A persistent session resumes when the client reconnects.
  • Guaranteed delivery: defined, per message. QoS 0 is at most once, QoS 1 at least once, QoS 2 exactly once through a four-step handshake (HiveMQ walks through the flows).
  • Ordering: defined, narrowly. A server must treat each topic as an “Ordered Topic”: messages from one client, on one topic, at one QoS, arrive in the order sent. HiveMQ notes that shared subscriptions break this, and that strict ordering is not guaranteed in a clustered broker.
  • Transactions: not addressed.
  • Clustering: not addressed.

A device that may lose its network mid-message needs to say, message by message, how much effort delivery deserves. QoS gives it exactly that, and nothing heavier.

STOMP: simple, because the broker does the rest

STOMP 1.2 is a text protocol, and its specification is candid: “STOMP does not define what the delivery semantics of destinations should be.”

  • Persistence: not addressed. Reliability semantics are server specific; ActiveMQ, as above, needs the persistent:true header.
  • Failover: partial. Heart-beating detects a dead connection; reconnecting is up to the client.
  • Guaranteed delivery: partial. Ack modes (auto, client, client-individual) and RECEIPT frames confirm what the server received or processed; what happens to the message next is the broker’s decision.
  • Ordering: not addressed.
  • Transactions: defined. BEGIN, COMMIT and ABORT group SEND, ACK and NACK frames, and a transaction left open when the client disconnects is aborted.
  • Clustering: not addressed.

STOMP buys reach, many clients in many languages, by keeping its frames simple. The guarantees come from whichever broker sits behind it.

XMPP: reliability added by extension

XMPP was designed for presence and chat between federated servers. Its core specification, RFC 6120, says that sending stanzas “can be unreliable” and that the core does not contain features to overcome this.

  • Persistence: partial. Storing messages for an offline recipient is a server practice described in XEP-0160, not a core rule.
  • Failover: partial. XEP-0198 Stream Management, a stable extension, adds stream resumption after a broken connection.
  • Guaranteed delivery: partial. The same extension adds acknowledgments of stanzas.
  • Ordering: partial. The core requires in-order processing of stanzas on a stream (RFC 6120, section 10.1); nothing orders messages across streams.
  • Transactions: not addressed.
  • Clustering: partial, in another sense. Server-to-server federation is part of the core, so messages cross domains; federation is not high availability.

OpenWire: strong, because it belongs to one broker

OpenWire is ActiveMQ’s own cross-language wire protocol, the default transport of its Java clients since version 4.

  • Persistence: defined. Following JMS, delivery is persistent by default, and persistent messages “survive a broker restart” (ActiveMQ).
  • Failover: defined. The failover transport reconnects to another broker from a list, and brokers can push changes in the cluster to connected clients.
  • Guaranteed delivery: defined. Acknowledgment and redelivery follow JMS, on top of persistent storage; after a failover, outstanding messages are redelivered before a transaction may commit.
  • Ordering: partial. ActiveMQ’s documentation states that total message ordering is not preserved across a network of brokers.
  • Transactions: defined. In-flight transactions are replayed after reconnection, and a commit in doubt is rolled back so the application can retry.
  • Clustering: partial. Networks of brokers store and forward messages between brokers; the protocol is what lets clients follow those topology changes.

OpenWire scores highest on failover because it is not neutral. It knows its broker, so it can carry the broker’s topology to the client. That knowledge is also the lock-in: Magnoni calls the protocol choice a decision about how tightly the application couples to the messaging system.

Message queue protocols side by side

PropertyAMQP 1.0MQTTSTOMPXMPPOpenWire
PersistenceDefinedPartialNot addressedPartialDefined
FailoverPartialPartialPartialPartialDefined
Guaranteed deliveryDefinedDefinedPartialPartialDefined
OrderingPartialDefinedNot addressedPartialPartial
TransactionsDefinedNot addressedDefinedNot addressedDefined
ClusteringNot addressedNot addressedNot addressedPartialPartial

Read the last row first: no protocol here defines clustering. XMPP federates and OpenWire follows a cluster, but building one is always the broker’s job.

Choosing among message queue protocols

  • Sends and acknowledgments that must commit together: AMQP 1.0, STOMP or OpenWire. MQTT and XMPP have no transactions.
  • Devices on poor networks: MQTT, choosing the QoS message by message.
  • Transparent failover with one broker vendor: OpenWire, accepting the coupling.
  • Interoperability between vendors: AMQP 1.0, then check which optional parts your broker implements, such as exactly once.
  • High availability: compare brokers, not protocols.

One choice can supplement another. A polyglot broker accepts several protocols at once: ActiveMQ, for one, serves STOMP and OpenWire clients side by side, so a lightweight producer and a transactional consumer can share the same queue.

Reading message queue protocols property by property pays off three ways: you know which guarantees the wire enforces, which ones depend on how your broker is configured, and where a stronger promise is being paid for with lock-in.

Pastel Gbetoho

0 Comments

You May Also Like