How to produce/send messages from multiple threads

Asked by Tvrtko on 2009-04-28

Hello,

I would like to use txAMQP as a client AMQP library from my multithreaded web application. All I have to do is send a message to RabbitMQ, no processing/consuming is necessary. What worries me is that I have to send message from multiple threads and txAMQP (twisted reactor) is designed (I guess) to be called from single thread. Is there a way to do this?

My idea was to create separete thread and inside it:
  * setup connection and channels
  * run twisted reactor with installSignalHandlers=0
  * monitor for lost connections and reconnect (subject on its own)
Then from other application threads:
  * call chan.basic_publish(...) without causing problems to txAMQP/twisted

Also, do you know how to monitor for lost connections and reconnect when necessary?

Regards,
Tvrtko

P.S.
Using twisted for my entire app is not an option.
I know there are other libraries (py-amqplib and qpid-python), but I want to use this one.

Question information

Language:
English Edit question
Status:
Solved
For:
txAMQP Edit question
Assignee:
No assignee Edit question
Solved by:
Tvrtko
Solved:
2009-06-18
Last query:
2009-06-18
Last reply:
2009-06-17
Esteve Fernandez (esteve) said : #1

I don't have much experience mixing threaded and Twisted code, but I guess your solution might work. Another approach would be to have two separate processes and use Thrift (or some other serialization mechanism) for passing data between them:

- a Twisted process, which uses txAMQP and listens on UNIX sockets or /dev/shm and receives txThrift calls (use thrift --gen py:twisted to generate Twisted-friendly services)
- a threaded process (e.g. Django), which uses the blocking version of Thrift to send requests to the previous process

Tvrtko (qvx3000) said : #2

You say my solution might work, but it is not a solution, just a beginning. What remains unexplained is how to call chan.basic_publish(...) without causing problems to txAMQP/twisted?

I thought that there might be a well understood way of doing this in twisted.

Your proposal to create another process and use Thrift just to send a message to a queue is doable but not acceptable. The creation of a third superfluous process which is used only as a relay... you are just introducing several new components (process,socket,thrift,deamonization...) that are increasing the system complexity

Dan Di Spaltro (dan-dispaltro) said : #3

So, I went down this path briefly using Django to send messages directly to RabbitMQ. The key for the firing up the reactor in a seperate thread was two things. First the passing false to the reactor.run(False), thus not interfering with signal handlers. Second is using callFromThread to execute the method, I have a very unfinished ReactorThread class that kind of handles the abstraction, if you want to see it. It is far from pretty and is super incomplete.

Remember if you are using something like mod_python and apache than the number of threads that get spun up is equivalent to the amount of worker processes.

Esteve Fernandez (esteve) said : #4

Thanks Dan!

Tvtrko, did Dan's solution work for you? Can I mark this question as solved?

As a side note, there was a related thread in twisted-python:

http://twistedmatrix.com/pipermail/twisted-python/2009-May/019681.html

and Jean Paul (a core Twisted developer) recommended a solution similar to the one I suggested to you:

http://twistedmatrix.com/pipermail/twisted-python/2009-May/019684.html
http://twistedmatrix.com/pipermail/twisted-python/2009-May/019697.html
http://twistedmatrix.com/pipermail/twisted-python/2009-May/019708.html

Hope that helps.

Tvrtko (qvx3000) said : #5

Yes, it helped!
Thanks