[rabbitmq-discuss] Use a mysql databse table as the provider for rabbitmq queue

Tim Watson tim at rabbitmq.com
Wed Oct 17 14:32:33 BST 2012


Hi Ryan,

On 10/17/2012 02:03 PM, Ryan R. wrote:
> Ok I've definitely got what you're trying to say concerning the use of 
> DBs and message broker.
>

Good, and your post has helped me to understand what you're doing more 
clearly, so this should get easier now.

> To explain a bit more, I'll answer the few questiosn you've scattered 
> across your reply :
>
> Is it a distributed architecture ?
>
> Definitely yes, each app will run on a different server
>

Ok, so that's more the classic integration architecture for sure.

> Why do I need to keep apps separate ?
>
> Simply because my project can be viewed as a application suite 
> composed of about 5 different apps. The end-user will be able to 
> choose which of the apps he wants and I want to only provide what is 
> absolutely necessary for the end-user based on what he asked for, 
> nothing more nothing less. Therefore if the end user only wants one 
> app out five I'm not going to provide him with a RabbitMQ, he will 
> have no use for it. However should he asked for a set of apps that 
> need to communicate, then I'll install a RabbitMQ to let them communicate.

Ok, well that is certainly do-able and I can understand the reasons why 
a particular customer site that doesn't need the middle-ware might as 
well skip it.

> Now like I said, I'm looking for a way to do this without changing 
> anything in the apps' code.
> What I'm looking for is a solution where I would have something like a 
> "watcher" external app that would keep an eye on what's going on in 
> each app and manage the content of each RabbitMQ queues accordingly.
>

Right, and in fact that's probably quite a common pattern in integration 
architectures. What I would ask is this: how are these applications 
supposed to know about the incoming data? And how, for that matter, is 
the data supposed to get into the queues in the first place?

Now, one solution to this is to do what you say and write a new 
application, a copy of which resides alongside each main app in the 
system and basically does two things:

1. periodically read data from the database for application 1 and write 
it to a queue
2. constantly (in a worker thread, or periodically in the main one) read 
data from a queue and write it to the application database

This is fine, in theory, as long as you bare in mind that what you're 
basically doing is making the overall system into a sort of 'shared 
database where tables are replicated/synchronised via queues'. Think 
about it a while and it's clear that, even if the tables being read from 
and/or written to are different, that basically you end up with the same 
thing. Then ask yourself if you'd design a distributed database that 
uses a messaging system as its replication back-bone.

Now I don't want to completely put you off that approach. It certainly 
has some things going for it: you do not need to change the application 
code anywhere, and if the application doesn't need the messaging system 
then you just avoid installing the 'watcher' process (and broker) in the 
first place. Job done!

There are things to consider with this approach though, which will 
re-enforce my point about it being like a distributed database that 
isn't. Consider some rhetorical questions about the systems that may or 
may not be communicating:

- do they rely on incoming information in order to do their job?
- does incoming information lead (causally) to more outgoing information?
- does outgoing information rely on future incoming information?
- and for any of the above, does the order in which information is 
handled ever matter?

If the answer to any of those questions is 'yes', then it might be worth 
reconsidering the use of a separate 'watcher'. All of those scenarios 
can lead to races, deadlocks and all manner of other problems usually 
associated with concurrent application development, because a 
distributed system that uses asynchronous message passing is 
*inherently* concurrent in nature and races/deadlocks/etc are all *much* 
harder to spot (and fix) when they're distributed!

> That peculiar aspect of the apps is for my longterm evolution of my 
> app : for my personal use, the simpler approach of the code for 
> pushing a mesage in the queues embedded in the app would be fine. But 
> since I'd like to make it evolve to something else, I'd rather think 
> ahead and try to do so right now.
>

Well, I'm unable to comment on the design choices for a technology I 
know nothing about, but I will offer this. If messaging is made into a 
specific (service) layer for an application, that application should 
usually be able to evolve without ever changing the messaging code. The 
event publication subsystem is, after all, a fairly static design point 
- you choose what to publish and when (which can, of course, be made 
configurable in any language/platform) and then just leave the 
publication code alone. The event listening subsystem is likewise fairly 
static. You start a worker thread (or external process) and register 
callbacks that get run when a message arrives. Just as with the 
publication subsystem, you can pass whatever callbacks you like and 
these can be chosen at build time *or* at runtime, possibly driven by 
configuration settings if that is required. Finally, the remaining 
problem is what to do when there *is no broker* because the application 
is standalone. I think this is fairly simple - just set a flag (or 
configuration value) when starting you application and let the event 
handling subsystems (both the listener and publisher) treat all function 
calls as a no-op when there is no broker to communicate with.

The great advantage of this approach, IMO, is precisely the one you seem 
to want - that the applications can be evolved over time to publish new 
data and/or respond to new (or existing) messages in varying ways. 
Providing you have the infrastructure to make decisions about what to do 
in callbacks based on configuration settings, you *might* even be able 
to add new behaviours to your applications without writing any code! ;)

But..... There is the up-front cost of embedding the messaging 
technology into your applications in the first place. Personally, I 
would not make that cost the primary driver behind the design decision 
though. In your shoes, I would consider carefully how the interactions 
between these applications work and understand the distribution and 
information sharing model they need to conform to first. Once that is 
clear, then you can decide whether or not the timing, ordering and/or 
existential questions about the system architecture as a whole really 
matter or not. If they don't, then you might as well choose the external 
'watcher' as this minimises the impact on your code base and simplifies 
your deployments. If, on the other hand, they do matter, then you should 
*very* carefully consider whether the decoupling that the 'watcher' 
offers is likely to be a hindrance or a help. If enough of those causal 
relationships in the information sharing model require coupling of some 
kind, then interacting directly with a messaging system (where you can 
choose whether or not you care about acknowledgements/receipts, 
batching, transactions/confirms, and other such features) might well 
prove to be architecturally important.

HTH and makes some degree of sense!

Cheers,
Tim

> Hope these explanations help a little more.
>
> Cheers,
> Ryan.
>
> 2012/10/17 Tim Watson <tim at rabbitmq.com <mailto:tim at rabbitmq.com>>
>
>     On 10/17/2012 11:40 AM, Ryan R. wrote:
>
>         I think I understand what you mean with the shared library.
>         However, in my case, RabbitMQ would only be installed if need
>         be (meaning more than one of the apps are present, and two of
>         those need to be synchronised for part of their data).
>
>
>     That actually complicates the picture somewhat - is there a reason
>     why this is the case? In a typical integration architecture, the
>     messaging broker is deployed centrally (on the LAN somewhere) and
>     clients choose whether or not they want to connect to it from
>     whatever machine they're running on. To me, it is sounding like
>     you're describing an architecture where both applications reside
>     on the same machine and assuming that the broker will also need to
>     be co-resident with them, which is not really the case, though
>     there's nothing to prohibit that either.
>
>
>         That said, using a shared library would require me to
>         "include/import" said library when I need to, therefore making
>         me change my app code depending of the situation I'm in.
>
>
>     Well yes, if you're going to add messaging capabilities to your
>     applications that don't currently support it, then you are going
>     to have to write *some* code and integrate it into them! :)
>
>
>         And said library would only be required when there's a
>         RabbitMQ available anyway.
>
>
>     I think you're making your life more complicated than it needs to
>     be by thinking about whether the messaging broker is available vs.
>     not. The broker should *always* be available when applications
>     residing on different machines need to communicate with one
>     another, regardless of whether those applications are running or
>     not. Again, it feels like you're trying to deal with applications
>     running on the same machine - have I picked that up correctly? It
>     might help if you explained your architecture in a bit more
>     detail, so I can understand exactly what you're trying to achieve.
>
>
>         Now a bit further in your message you talk about a listener
>         library.
>         I'd like to know a bit more about this.
>         How would an external library be able to listen to anything
>         happening within my app ?
>         Would it be listening on the DB queries ?
>
>
>     No, not at all. Let's say you've got two applications, App1 and
>     App2. You'll write some library code that both applications share,
>     that probably looks something like this (with *wide* variations
>     depending on language/platform - I've just written pseudo code to
>     keep things simple):
>
>     -------------------------------------
>
>     function init = do
>         read_config_file_for_this_app
>         open_connection_to_broker
>         store_connection_somewhere_in_memory
>     end
>
>     function listen = do
>         get_connection_from_memory
>         read_message_from_broker
>         pass_message_to_application_thread_somehow
>         listen
>     end
>
>     function publish = do
>         get_connection_from_memory
>         send_message_to_broker
>     end
>
>     -------------------------------------
>
>     Now in your applications, you'll call the shared 'init' library
>     function when you're starting up to bootstrap the connection to
>     the broker. When your application is publishing data, it calls
>     publish and if/when you need to subscribe to data then you'll call
>     'listen'. The fact is that 'how to listen' for incoming messages
>     really depends on how you're going to use them. But the point is
>     that the applications read from and write to the messaging broker,
>     and do so independently of database tables. You *may* decide to do
>     something like write a middle-man application that periodically
>     reads a database table and publishes each row to the messaging
>     broker so it can be read from a queue, or do that with a worker
>     thread instead of a separate application. I would *not* do
>     anything here with the database though. If applications need to
>     share data, then **they should send it to one another via message
>     queues.** If they need to persist data, they should persist their
>     own data in their own tables in the database, but they should
>     **not use the database to communicate with one another.** That is
>     the key thing with using messaging instead shared data(bases).
>
>     There is an overhead in sending (and in some cases, duplicating)
>     data between applications of course. This is *more* than
>     compensated for by the reduced coupling that comes from
>     integrating using messaging technology. This approach may not be
>     suited to integrating applications that are running on the same
>     physical machine and are tightly and deliberately coupled however.
>     I can't really elaborate on the suitability of messaging for your
>     project without understanding a good deal more about it I'm afraid.
>
>     I hope that clears a few things up at least! :)
>
>     Cheers,
>     Tim
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/attachments/20121017/79ed34af/attachment.htm>


More information about the rabbitmq-discuss mailing list