2016-09-22 102 views
0

我正在运行一个简单的Tornado Flask应用程序,但视图一次只处理一个请求。我怎样才能使它处理多个并发请求?Flask和Tornado Applciation不处理多个并发请求

我正在使用的修复程序是fork和使用多个进程来处理请求,但我不喜欢该解决方案。

from flask import Flask 

app = Flask(__name__) 

@app.route('/flask') 
def hello_world(): 
    return 'This comes from Flask ^_^' 

from tornado.wsgi import WSGIContainer 
from tornado.ioloop import IOLoop 
from tornado.web import FallbackHandler, RequestHandler, Application 
from flasky import app 

class MainHandler(RequestHandler): 
    def get(self): 
    self.write("This message comes from Tornado ^_^") 

tr = WSGIContainer(app) 

application = Application([ 
    (r"/tornado", MainHandler), 
    (r".*", FallbackHandler, dict(fallback=tr)), 
]) 

if __name__ == "__main__": 
    application.listen(8000) 
    IOLoop.instance().start() 

回答

3

最直接的答案是,你应该使用专用的WSGI服务器,如uWSGI或Gunicorn,并将其配置为使用多个工人。不要将龙卷风作为WSGI服务器。


你的产卵过程的修正是正确的,尽管使用WSGI与Tornado是“正确的”。 WSGI是一个同步协议:一个工作者一次处理一个请求。 Flask不知道Tornado,所以使用协程不能很好地处理它:处理请求同步发生。

Tornado has a big warning in their docs about this exact thing.

WSGI是同步接口,而龙卷风的并发模型基于单线程异步执行。这意味着运行带有Tornado的WSGIContainer的WSGI应用程序比在多线程WSGI服务器(如gunicornuwsgi)中运行相同应用程序的可扩展性更低。只有在将Tornado和WSGI合并到同一个过程中才能获得好处的情况下,才能使用WSGIContainer,这个过程大大降低了可伸缩性。

换句话说:处理更多的并发请求与WSGI应用程序,产生更多的工人。工作者的类型也很重要:线程与流程与事件小部件都有折衷。您通过自己创建流程来产生工作人员,但使用WSGI服务器(如uWSGI或Gunicorn)更为常见。

+0

其实这并不完全正确。 WSGI支持一个协同接口,你可以返回一个* iterable *(这可能是一个生成器),而不是完整的结果。不幸的是,并不是很多中间件都使用这个(我不知道)。 –

+0

@JonasWielicki如果你有更多的信息会很棒,但我认为你可能会让人感到困惑。返回一个生成器允许流式响应(Flask支持这个),但是一个worker仍然处理一个响应。 – davidism

+0

问题在于Flask/Werkzeug不知道如何使用Tornado,所以处理请求,运行视图和产生初始响应的所有事情都发生在Tornado的同步范围内。 – davidism