Real time system
Tomas (t0m) Doran
São Paulo.pm perl workshop 2010
Aka the “my code
doesn’t work yet” talk
• I wrote half the slides for this at 6am Friday
(São Paulo time)
• The title is a bit misleading, as I wrote the
talk abstract in March, then wrote entirely
• Sorry about that.
• Lets not talk about the (not working) code
• This talk is about Message Queueing.
• What is Message Queueing?
• Why would I want to use it?
What is message
• In it’s simplest form, it’s just a list.
• 1 (or more) ‘producers’ (writers)
• 1 (or more) ‘consumers’ (readers)
• Queue if rate of production > rate of
Why do I want it?
• Decouples producers and consumers
(probably across the network).
• Lets you manage load, and spikes in load
(only n consumers).
• In a web environment - lets you serve
more pages, quicker.
• View as a list a little simplistic.
• Depending on your application, you may
• One to one
• One to many
• One to many (broadcast)
• Many to all of the above
• More complex topology?
• Queuing protocol
• Interoperable (maybe?)
AMQP enables complete
interoperability for messaging
middleware, both the networking
protocol and the semantics of broker
services are deﬁned in AMQP.
• Full abstraction of all the mechanics of
messaging across the network.
• Serialization and framing of messages.
• Wiring of message routing is part of the
• So all your clients know (at least half) of
• Different topologies depending on routing
• Can specify other options such as durability
• Nice when your server dies - no ‘current
Concepts - Exchanges
• Messages are published (sent) to one
• Can be durable (lasts till deleted), or auto-
• Queues can be named or (or named by the
server - private queues).
• Queues are bound to one (or more)
• Queues can have 0 or more clients
• Queues may persist with 0 clients or not.
• FIFO (if you have 1 consumer)
• Message never delivered to > 1 client
• Binding is what joins a queue and an
• Named exchange
• Bound to 1 Named queue
• 0 or more listeners get round-robin
• Messages queue when nobody listens / if
consumers are slow
• Named exchange
• Each client creates an anonymous
• Client binds the queue to that exchange
• All clients get all messages
• Messages go to /dev/null if no clients
• Different exchange types - direct, topic,
• You can do a lot using just these and a mix
of named and anonymous queues
• More complex topologies possible
I accidentally wrote
• I try to avoid doing this
• I’m not very good at it ;)
I blame Net::RabbitFoot
• It’s written using AnyEvent and Coro
• Which I hadn’t used before, but looked
good for this type of thing.
• I felt my way around writing simple things
• Got all the web servers logging into Rabbit
Logging into message
• Good example of broadcast
• Want to aggregate logs to ﬁles
• And be able to ‘tail’ them
• Logging directly from the application
• Also tailing (normal) log ﬁles to message
Dumping them to a ﬁle
• That’s pretty simple after that..
• Log rotation
• Not ﬂushing to disk once per message
Viewing them live
• Someone wrote an AMQP client in ﬂash
• AMQP security model not useful publicly
• Cute prototype
• (Sorry, no demo - refuses to work locally)
• Next application, simple job queue.
• 1 worker, serialized.. (Crap, good enough)
• Log JSON into RabbitMQ (again), inﬂate,
call the ->run method.
• I now have several scripts, all doing bits
with queuing. All duplicating code.
• I want to aggregate messages
• Send messages of aggregates at regular
• Need something more generic
• Wrote a simple abstraction on getting
channels, making exchanges and queues, etc
• Was still going to end up with a load of
scripts/jobs that needed running and
• Inspecting the state of each job ‘service’
hard / boring..
• Each ‘thing’ (timer, listener, logger, emitter,
worker etc) can be an instance of a class
with attributes for the state.
• Construct a set from some conﬁg ﬁle.
• Lets me aggregate jobs together / share
code (Can use AnyEvent/Coro for threads).
• Less processes to manage. Working out the
state just got harder still.
• Make all the classes use MooseX::Storage
• Catalyst makes instances of things from
• So, I could adapt all these instances into
Catalyst models, write a controller, done!
• Erm, but Catalyst, and message queueing,
I blame Miyagawa
• For Plack, and Catalyst::Engine::Plack, and
Corona (the Coro PSGI server).
• I had this INSANE idea one night.
• I tried it.
• IT WORKED.
I blame clkao
• Next step - browser kicks off a job.
• Status via long poll?
• He did it already!
• With long hair!
• Async pipe to the browser.
• Abstracts all the nasty ajax details (also
does long poll, or websockets)
• Automatically updated monitor of app
• Start a job and then get an AJAX update
screen for the job progress.
• The basics work.
• Running it production at work
• (Since WedneThursday....)
• If you need a high volume, simple,
production ready job scheduler right
now, use Gearman.
• Needs my github versions of
Catalyst::Engine::PSGI and Web::Hippie
• Running jobs from the web app doesn’t
• All the pieces are there - next week?
• Production battle scars ;)
• Hippie for watching jobs run, not just
component status updates.
• Docs would be good...
• Hippe::Pipe for bidirectional
• More traits / plugins / components
What to go look at
• Docs, setup info, FAQ
• Slideshare - lots of good and more detailed
What to go look at
• CatalystX::JobServer (github)
• I forgot to mention this originally...
• DO NOT FORK AFTER USING
Net::RabbitFoot (and then try to use it in
the child process)
• This will go horribly horribly wrong.
• ActiveMQ (or Rabbit has a STOMP
• Anyone interested in playing, grab me on irc
• Happy to hand-hold as I need more people
• I’ll love you forever if you write docs.
A particular slide catching your eye?
Clipping is a handy way to collect important slides you want to go back to later.