所以我在下面有一个处理程序:
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作为数据库,而我正在尝试做的事情相对简单。
我有一个用户数据库,每个用户都有一个过滤器。如果过滤器与消息匹配,则服务器将消息发送给用户。目前我正在测试成千上万的用户,因此每次通过帖子请求发布消息时,它都会迭代数千个用户来查找匹配项。这是我做事的天真实施,因此也是我的问题。我该如何做得更好?
答案 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)
...
但这些都是充其量的黑客。我正在寻找一个更好的解决方案,可能最终会得到一些消息队列或简单的线程解决方案。