想象一下以下龙卷风应用:为什么Tornado的WSGI支持会阻止多个请求?
import logging
import time
from tornado import gen, httpserver, ioloop, web, wsgi
def simple_app(environ, start_response):
time.sleep(1)
status = "200 OK"
response_headers = [("Content-type", "text/plain")]
start_response(status, response_headers)
return [b"Hello, WSGI world!\n"]
class HelloHandler(web.RequestHandler):
@gen.coroutine
def get(self):
yield gen.moment
self.write('Hello from tornado\n')
self.finish()
def main():
wsgi_app = wsgi.WSGIContainer(simple_app)
tornado_app = web.Application(
[
('/tornado', HelloHandler),
('.*', web.FallbackHandler, dict(fallback=wsgi_app)),
],
debug=True,
)
http_server = httpserver.HTTPServer(tornado_app)
http_server.listen(8888)
current_loop = ioloop.IOLoop.current()
current_loop.start()
if __name__ == '__main__':
main()
现在,如果你运行这个并试图让http://localhost:8888/
龙卷风块,直到WSGI请求完成(一秒睡眠后在这里)。这件事我知道。但是,如果您一个接一个地发送很多请求,那么IOLoop可能会永久封锁。
我想这样的标杆:
$ ab -n 20 -c 2 localhost:8888
在第二端我试图让其他网址:
$ curl http://localhost:8888/tornado
我得到了非WSGI请求的响应直到所有其他并发的WSGI请求已完成。这仅适用于已删除yield gen.moment
的情况。
任何人都可以解释这里发生了什么,以及如何防止Tornado阻止我的所有请求,而不仅仅是其中之一?
非常感谢。我将WSGI和Tornado结合起来可以带来一些好处,所以我希望通过稍后使用优先级队列来减少阻塞问题,以便在一次阻塞WSGI调用后,Tornado运行IOLoop,并且每个人都有机会在下一次之前进入中间层阻止WSGI呼叫。但是,如果Tornado没有运行IOLoop,只要有任何*未完成的WSGI请求,这将不起作用。 – Norman8054