The STOMP gateway is an implementation of the STOMP protocol that is backed by RabbitMQ, providing for interoperation between STOMP clients, AMQP clients and others.
You can get the code by checking it out from our repository with
hg clone http://hg.rabbitmq.com/rabbitmq-stomp/
You can browse the code and see a listing of changesets at
Announcements regarding the gateway are periodically made on the RabbitMQ MailingList, and on LShift's blog.
About STOMP:
Blog posts about the gateway:
There's also been occasional discussion of the gateway on the MailingList, including:
While STOMP's syntax is defined fairly clearly, its semantics are much less clear. The RabbitMQ STOMP gateway tries to stick to the protocol definition; however, STOMP doesn't define enough syntax to cover all the functionality that AMQP provides, so the gateway provides some extensions to the core protocol.
The way AMQP works is that messages are
As messages pass through an exchange, they are duplicated, and a copy is sent down each activated binding.
In contrast, when messages leave a queue for a consumer, they are not duplicated. One message, sitting on a queue, is delivered to only one of the available consumers. Only if that consumer rejects the message somehow (e.g. by crashing or otherwise disconnecting before it acknowledges the message) will the message be sent on by the queue to some other consumer.
With the STOMP adapter, a plain old
SUBSCRIBE destination: myqueue
will create a new consumer. If there are multiple clients, all
SUBSCRIBEing to the same queue, then there will be multiple consumers
all on the same queue, leading to round-robin delivery to those clients.
In order to get broadcast behaviour, you need to use a feature (originally contributed by Artur Bergman, now present in the trunk) which exposes a little more of AMQP's semantics through STOMP:
SUBSCRIBE id: da9d4779-92b9-4cef-86c0-800bdc977f15 destination: exchange: amq.topic routing_key: #
The empty-string used for the "destination" header tells the adapter to
create a private queue for this one subscription, which will last for
the duration of your connection, or until you UNSUBSCRIBE.
The "id" header should be some string unique to the current connection (!) which names the subscription. I've used a fresh GUID here, but anything connection-unique is acceptable.
If you omit the "id" header, the current implementation has a wart
meaning you won't be able to issue more than one SUBSCRIBE with an empty
destination string; we could remove that if absolutely required, but in
my view it's all round simplest and best just to require an "id" header.
The "exchange" header tells the adapter to bind the new private queue to the named exchange. All AMQP brokers come with preconfigured "amq.direct", "amq.topic" and "amq.fanout" exchanges, with semantics described by the AMQP specification (section 3.1.3 of the 0-8 specification PDF). The "routing_key" header is used as described in ยง3.1.3 to select which messages are copied into the queue by the exchange.
The STOMP gateway doesn't provide a way of creating a new exchange, yet; you have to use a real AMQP client (one that can issue "exchange.declare" commands) for that, currently. Suggestions welcome!
To unsubscribe from a private queue,
UNSUBSCRIBE id: da9d4779-92b9-4cef-86c0-800bdc977f15
as usual, supplying the same "id" you supplied to the SUBSCRIBE.
The private queue will be deleted when the UNSUBSCRIBE has completed.
This changeset contains some Ruby examples of topic broadcast, private-queue creation, and unsubscription.
See the instructions in the README that ships with the code.