使龙卷风在单独的线程上提供请求

时间:2014-09-24 10:55:13

标签: python web-services flask tornado

我有一个用 Flask 编写的网络服务,包含在WSGIContainer中,并由 Tornado 使用其FallbackHandler机制提供服务。 flask webservice中的一个路径运行一个非常长的操作(大约需要5分钟完成),当触发此路由时,阻止对任何路由的每个其他调用,直到操作完成。我该如何解决这个问题?

以下是使用 Tornado 提供 Flask 应用程序的方式:

parse_command_line()

    frontend_path = os.path.join(os.path.dirname(__file__),"..","webapp")

    rest_app = WSGIContainer(app)
    tornado_app = Application(
        [
            (r"/api/(.*)", FallbackHandler, dict(fallback=rest_app)),
            (r"/app/(.*)", StaticFileHandler, dict(path=frontend_path))
        ]
    )

3 个答案:

答案 0 :(得分:3)

Tornado的WSGI容器不具有很高的可扩展性,只有在您有特定理由在同一进程中组合WSGI和Tornado应用程序时才能使用它。 Tornado不支持长时间运行的WSGI请求;任何可能需要很长时间的事情都需要使用Tornado的本机异步接口而不是WSGI。

请参阅warning in the docs

  

WSGI是一个同步接口,而Tornado的并发模型基于单线程异步执行。这意味着使用Tornado的WSGIContainer运行WSGI应用程序的可伸缩性低于在多线程WSGI服务器(如gunicorn或uwsgi)中运行相同的应用程序。仅当在同一进程中将Tornado和WSGI组合在一起的好处超过降低的可伸缩性时,才使用WSGIContainer。

答案 1 :(得分:1)

您可以考虑使用tornado-threadpool,在这种情况下,您的请求会立即返回,任务将在后台完成。

from thread_pool import in_thread_pool
from flask import flash

@app.route('/wait')
def wait():
    time_consuming_task()
    flash('Time consuming task running in backround...')
    return render_template('index.html')

@in_thread_pool
def time_consuming_task():
    import time
    time.sleep(5)

答案 2 :(得分:0)

您可以使用Ladon的任务类型方法进行这些长时间的操作。

它为这些类型的情况提供了框架解决方案。

Ladon Tasks documentation