Python Tornado - 在异步功能继续工作的同时立即返回POST

时间:2010-10-06 04:02:20

标签: python tornado

所以我在下面有一个处理程序:

class PublishHandler(BaseHandler):

    def post(self):
        message = self.get_argument("message")
        some_function(message)
        self.write("success")

我面临的问题是some_function()需要一些时间来执行,我希望post请求在被调用时立即返回,并且如果可能的话,some_function()将在另一个线程/进程中执行。 / p>

我正在使用berkeley db作为数据库,而我正在尝试做的事情相对简单。

我有一个用户数据库,每个用户都有一个过滤器。如果过滤器与消息匹配,则服务器将消息发送给用户。目前我正在测试成千上万的用户,因此每次通过帖子请求发布消息时,它都会迭代数千个用户来查找匹配项。这是我做事的天真实施,因此也是我的问题。我该如何做得更好?

2 个答案:

答案 0 :(得分:7)

您可以使用IOLoop的{​​{1}}方法完成此操作:

add_callback

Tornado将在下一个IOLoop传递中执行回调,可能(我必须深入了解Tornado的内容,以确定或者测试它)允许请求在此之前完成代码被执行。

缺点是你编写的长时间运行的代码仍然需要时间来执行,这可能最终会阻止另一个请求。如果您有很多这样的请求立即进入,那就不理想了。

更简单的解决方案是在单独的线程或进程中运行它。使用Python的最佳方式是使用一个进程,因为GIL(如果你不熟悉它,我强烈建议你阅读它)。但是,在单处理器机器上,线程实现可以正常工作,并且可能更容易实现。

如果您要使用线程路由,则可以使用互斥锁,线程和队列构建一个漂亮的“异步执行程序”模块。如果您想使用单独的流程,请查看loop.add_callback(lambda: some_function(message)) 模块。

答案 1 :(得分:1)

我试过这个,我相信在调用回调之前请求没有完成。

我认为肮脏的黑客会调用两个级别的add_callback,例如:

  def get(self):
    ...
    def _defered():
      ioloop.add_callback(<whatever you want>)
    ioloop.add_callback(_defered)
    ...

但这些都是充其量的黑客。我正在寻找一个更好的解决方案,可能最终会得到一些消息队列或简单的线程解决方案。