The subject of messaging systems came up in a conversation last week, and some
wheels started turning. I like the idea of messaging systems. It feels
architecturally clean to have all your components abstracted away from each
other, so that each one only sees the message bus, and doesn’t give a hoot where
its messages are going to, or coming from. Even more specifically, each
component can choose which messages it wants to get, and not be bothered with
the rest. This again feels tidy.
Not only do messaging systems give you an architectural layer of abstraction,
but you also get the thing that prompted this post: temporal decoupling. If
you have a part of the system that isn’t running 24/7, you can either build
‘time-locks’ into the UI so that it can only be accessed when the system is up,
or you could use a combination of an off-line cache and a store-and-forward
message queue to allow the system to be used in limited fashion even when parts
of it are temporarily down. The cache can be implemented as ‘just another
subscriber’ to the message queue. Another bonus: adding message consumers is
transparent to message producers, and vice versa. This allows a many-to-many
relationship between components, such that multiple machines can look like one
big virtual one to anything on the other side of the message queue.
Disadvantages? Two network hops (Producer-Queue-Consumer) where before there
was only one. Added development complexity. System administration – now
there’s a message queue component to look after as well. Point of failure –
losing your message queue would not be funny. The store-and-forward approach
would not work well for time-critical messages (eg. stock market transactions).
Better to report failure immediately than complete the transaction at some
indeterminate point in the future, when market conditions may be wildly different.