【问题标题】:Python Tornado - making POST return immediately while async function keeps workingPython Tornado - 在异步函数继续工作时立即返回
【发布时间】:2010-10-06 04:02:20
【问题描述】:

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

class PublishHandler(BaseHandler):

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

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

我使用的是berkeley db作为数据库,我想做的比较简单。

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

【问题讨论】:

    标签: python tornado


    【解决方案1】:

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

    loop.add_callback(lambda: some_function(message))
    

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

    缺点是您编写的长时间运行的代码仍然需要时间来执行,这最终可能会阻塞另一个请求。如果您同时收到大量此类请求,那就不太理想了。

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

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

    【讨论】:

      【解决方案2】:

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

      我认为一个肮脏的技巧是调用两个级别的 add_callback,例如:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-13
        • 2020-10-26
        • 1970-01-01
        • 2018-06-04
        • 1970-01-01
        • 2019-09-02
        • 2019-10-13
        • 1970-01-01
        相关资源
        最近更新 更多