7

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

class PublishHandler(BaseHandler):

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

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

我使用 berkeley db 作为数据库,我想做的事情相对简单。

我有一个用户数据库,每个用户都有一个过滤器。如果过滤器与消息匹配,则服务器将消息发送给用户。目前我正在与数千名用户进行测试,因此在每次通过发布请求发布消息时,它都会遍历数千名用户以找到匹配项。这是我做事的幼稚实现,因此是我的问题。我怎样才能更好地做到这一点?

4

2 回答 2

7

您可以通过使用您IOLoopadd_callback方法来完成此操作,如下所示:

loop.add_callback(lambda: some_function(message))

Tornado 将在下一个 IOLoop 传递中执行回调,这可能(我必须深入研究 Tornado 的胆量才能确定,或者测试它)允许请求在该代码执行之前完成。

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

更万无一失的解决方案是在单独的线程或进程中运行它。由于 GIL,使用 Python的最佳方法是使用进程(如果您不熟悉它,我强烈建议您阅读它)。然而,在单处理器机器上,线程实现同样可以正常工作,而且实现起来可能更简单。

如果你要走线程路线,你可以用互斥锁、线程和队列构建一个不错的“异步执行器”模块。multiprocessing如果您想使用单独的流程,请查看该模块。

于 2010-10-06T04:42:22.820 回答
1

我已经尝试过了,我相信在调用回调之前请求没有完成。

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

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

But these are hacks at best. I'm looking for a better solution right now, probably will end up with some message queue or simple thread solution.

于 2010-12-09T02:35:57.220 回答