我正在尝试将简单的同步服务器转换为异步版本,服务器接收邮件请求,并从外部Web服务(amazon sqs)检索响应。这是同步代码
def post(self):
zoom_level = self.get_argument('zoom_level')
neLat = self.get_argument('neLat')
neLon = self.get_argument('neLon')
swLat = self.get_argument('swLat')
swLon = self.get_argument('swLon')
data = self._create_request_message(zoom_level, neLat, neLon, swLat, swLon)
self._send_parking_spots_request(data)
#....other stuff
def _send_parking_spots_request(self, data):
msg = Message()
msg.set_body(json.dumps(data))
self._sqs_send_queue.write(msg)
在这里阅读Tornado文档和一些线程我使用coroutines结束了这段代码:
def post(self):
zoom_level = self.get_argument('zoom_level')
neLat = self.get_argument('neLat')
neLon = self.get_argument('neLon')
swLat = self.get_argument('swLat')
swLon = self.get_argument('swLon')
data = self._create_request_message(zoom_level, neLat, neLon, swLat, swLon)
self._send_parking_spots_request(data)
self.finish()
@gen.coroutine
def _send_parking_spots_request(self, data):
msg = Message()
msg.set_body(json.dumps(data))
yield gen.Task(write_msg, self._sqs_send_queue, msg)
def write_msg(queue, msg, callback=None):
queue.write(msg)
使用围攻比较性能我得知第二个版本甚至比原版更差,所以可能有一些关于协同程序和Torndado异步编程的东西,我根本不理解。 你能帮帮我吗?
编辑: self._sqs_send_queue
这是从boto接口检索到的队列对象,queue.write(msg)
返回已写入队列的消息
答案 0 :(得分:0)
tornado
依赖于您将所有I / O转换为非阻塞。简单地在gen.Task
内部使用之前使用的相同代码根本不会提高性能,因为I / O本身仍然会阻止事件循环。此外,您需要将post
方法设为协程,并使用_send_parking_spots_requests
调用yield
以使代码正常运行。因此,“正确”的解决方案看起来像这样:
@gen.coroutine
def post(self):
...
yield self._send_parking_spots_request(data) # wait (without blocking the event loop) until the method is done
self.finish()
@gen.coroutine
def _send_parking_spots_request(self, data):
msg = Message()
msg.set_body(json.dumps(data))
yield gen.Task(write_msg, self._sqs_send_queue, msg)
def write_msg(queue, msg, callback=None):
yield queue.write(msg, callback=callback) # This has to do non-blocking I/O.
在此示例中,queue.write
需要是一些使用非阻塞I / O发送请求的API,并在收到响应时执行callback
。如果不确切知道原始示例中的queue
究竟是什么,我无法准确指出在您的案例中如何实现。
修改:假设您使用的是boto
,您可能需要查看实施bototornado
的the exact same API I described above:
def write(self, message, callback=None):
"""
Add a single message to the queue.
:type message: Message
:param message: The message to be written to the queue
:rtype: :class:`boto.sqs.message.Message`
:return: The :class:`boto.sqs.message.Message` object that was written.