[rabbitmq-discuss] [Q] best way to add a sequencer to the broker
Chuck Remes
cremes.devlist at mac.com
Mon Dec 29 14:04:21 GMT 2008
In my application I would like to stamp each message on the bus with a
sequence number. Doing so allows me to replay events in order (amongst
other benefits). Some services will be publishing latency-sensitive
information.
Each service connecting to the broker will publish to a topic
exchange. One to N other services may subscribe to the published data.
I foresee a topic hierarchy like so:
out.topic1 (passive, durable)
out.topic2 (passive, non-durable)
out.topic3.subtopic1 (passive, non-durable)
out.topic3.subtopic2 (passive, durable)
etc.
These exchanges are named with dot notation for simplicity of parsing
for regular expressions. I realize the exchange name doesn't need the
dot notation whereas that is a requirement for routing keys.
All of my data is serialized as a JSON object prior to publishing. The
object (hash) contains a key called :sequence which is set to 0 by the
publisher. The sequencer service will subscribe to all out.# topics
(with '#' as the routing key so it gets everything), read the content
body as a Map, and set the map :sequence value to i++ where 'i' is a
32-bit (or 64-bit) integer. It will then republish the JSON object to
a new topic of the form "in.topicX" and pass through the original
routing key. It's routing between, for example, out.topic1 and
in.topic1 and adding a sequence number as a side effect.
I played around with the examples SimpleTopicPublisher and
SimpleTopicConsumer as a basis for a new class. I was able to add a
JSONReader and JSONWriter to the new java class I call Sequencer. It
successfully performs the work as described in the prior paragraph.
RIght now I statically declare the in & out exchanges, but I see how I
could declare the "in" exchange based on the contents of the "out"
exchange name received in the envelope.
I have a few outstanding questions that I'm hoping some more
experienced folks can help answer.
1. This code will likely start before other services, so it will
declare the exchanges and block on them while waiting for traffic. The
topic Consumer/Producer examples all illustrate how to do this with a
single exchange. How do I accomplish this task with multiple
exchanges? Do I need a separate thread and channel for each exchange?
2. Is there a better way to accomplish this task? I've read some notes
about future releases of rabbitmq allowing for "internal" clients that
run inside the rabbitmq memory space. I think this is an ideal use of
that capability. Am I right or barking up the wrong tree? And does
that internal client need to be written in erlang or can it be java/c/
whatever?
3. Is there a way to make this more dynamic so I do not have to
declare all the exchanges up-front in this sequencer code? Ideally
this service could detect that new exchanges were declared by other
services and automatically subscribe to them to do the sequence
stamping and routing.
Thanks for any feedback.
cr
More information about the rabbitmq-discuss
mailing list