I have an AMQP server ( RabbitMQ ) that I would like to publish and read a web server in Tornado . For this, I decided that I would use the python amqp asynchronous library; in particular Pika (an option that Tornado allegedly supports).
I wrote code that seems to be successfully read from the queue, except that at the end of the request I get an exception (the browser returns a fine):
[E 101219 01:07:35 web:868] Uncaught exception GET / (127.0.0.1) HTTPRequest(protocol='http', host='localhost:5000', method='GET', uri='/', version='HTTP/1.1', remote_ip='127.0.0.1', remote_ip='127.0.0.1', body='', headers={'Host': 'localhost:5000', 'Accept-Language': 'en-us,en;q=0.5', 'Accept-Encoding': 'gzip,deflate', 'Keep-Alive': '115', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'User-Agent': 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101206 Ubuntu/10.10 (maverick) Firefox/3.6.13', 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'Connection': 'keep-alive', 'Cache-Control': 'max-age=0', 'If-None-Match': '"58f554b64ed24495235171596351069588d0260e"'}) Traceback (most recent call last): File "/home/dave/devel/lib/python2.6/site-packages/tornado/web.py", line 810, in _stack_context yield File "/home/dave/devel/lib/python2.6/site-packages/tornado/stack_context.py", line 77, in StackContext yield File "/usr/lib/python2.6/contextlib.py", line 113, in nested yield vars File "/home/dave/lib/python2.6/site-packages/tornado/stack_context.py", line 126, in wrapped callback(*args, **kwargs) File "/home/dave/devel/src/pika/pika/tornado_adapter.py", line 42, in _handle_events self._handle_read() File "/home/dave/devel/src/pika/pika/tornado_adapter.py", line 66, in _handle_read self.on_data_available(chunk) File "/home/dave/devel/src/pika/pika/connection.py", line 521, in on_data_available self.channels[frame.channel_number].frame_handler(frame) KeyError: 1
I'm not quite sure that I am using this library correctly, so I can do something egregious. The main stream of my code:
- Request comes in
- Create a connection to RabbitMQ using TornadoConnection; specify callback
- In the connection callback, create a channel, declare / bind my queue, and call basic_consume; specify callback
- When calling a callback, close the channel and call the Tornado termination function.
- See exception.
My questions are several:
- Is this thread right? I am not sure what the purpose of the callback of the connection is, except that it does not work if I do not use it.
- Should I create one AMQP connection for each web request? The RabbitMQ documentation suggests that no, I shouldn't, but I should stick to creating only channels. But where should I create the connection and how will I try to reconnect if it drops briefly?
- If I create one AMQP connection for each web request, where should I close it? The call to amqp.close () in my callback seems to hurt even more.
I will try a little sample code a bit later, but the steps described above completely consume some of the consumption. I also have problems with the publishing side, but queue consumption is more relevant.