Tornado 不能异步工作
Tornado doesn't work asynchronously
我正在尝试使用 tornado 编写非阻塞 api。但是当我在本地尝试时,第一个请求阻止了 API。我尝试使用不同的浏览器,但结果是一样的。
我打开了 chrome 和 firefox。在 chrome 我从 firefox 转到 http://localhost:8888/test-first and while it is loading I immediatly go http://localhost:8888/test-second。
我期待来自 firefox 的请求在另一个仍在加载时得到答复。但是他们都在等待,当第一个请求完成时,他们都完成了。
我的代码和输出:
期望控制台输出:
First request: 2017-11-22 22:23:22.093497
Second request: 2017-11-22 22:23:24.580052
Second answer: 2017-11-22 22:23:25.580509
First answer: 2017-11-22 22:23:37.579263
控制台输出
First request: 2017-11-22 22:23:22.093497
First answer: 2017-11-22 22:23:37.579263
Second request: 2017-11-22 22:23:37.580052
Second answer: 2017-11-22 22:23:37.580509
test_first.py:
import tornado.web
import datetime
class First(tornado.web.RequestHandler):
@tornado.web.asynchronous
async def get(self):
print("First request: " + str(datetime.datetime.now()))
for _ in range(1000000000):
pass
self.set_status(200)
self.write("OK")
self.finish()
print("First answer: " + str(datetime.datetime.now()))
test_second.py:
import tornado.web
import datetime
class Second(tornado.web.RequestHandler):
@tornado.web.asynchronous
async def get(self):
print("Second request: " + str(datetime.datetime.now()))
self.set_status(200)
self.write("OK")
self.finish()
print("Second answer: " + str(datetime.datetime.now()))
app.py:
import tornado
from test_first import First
from test_second import Second
class Application(tornado.web.Application):
def __init__(self):
ENDPOINTS = [
# USERS #
(r"/test-first", First),
(r"/test-second", Second)
]
SETTINGS = {
"debug": True,
"autoreload": True,
"serve_traceback": True,
"compress_response": True
}
tornado.web.Application.__init__(self, ENDPOINTS, SETTINGS)
if __name__ == "__main__":
print("dinliyor...")
Application().listen(8888)
tornado.ioloop.IOLoop.instance().start()
for _ in range(1000000000):
pass
这是一项 CPU 密集型任务。因此,它会阻止整个服务器。 Tornado 和几乎所有其他异步库都用于执行异步网络 I/O,这意味着,数据进来,数据出去——没有繁重的 CPU 任务。
要执行 CPU 绑定阻塞任务,您必须 运行 在单独的进程或线程中执行它,这样它就不会阻塞服务器。
但无论如何,要获得预期的输出,您可以使用 tornado.gen.sleep
.
暂停 First
处理程序
class First(tornado.web.RequestHandler):
@tornado.web.asynchronous
async def get(self):
print("First request: " + str(datetime.datetime.now()))
await tornado.gen.sleep(5) # sleep for 5 seconds
self.set_status(200)
...
我正在尝试使用 tornado 编写非阻塞 api。但是当我在本地尝试时,第一个请求阻止了 API。我尝试使用不同的浏览器,但结果是一样的。
我打开了 chrome 和 firefox。在 chrome 我从 firefox 转到 http://localhost:8888/test-first and while it is loading I immediatly go http://localhost:8888/test-second。
我期待来自 firefox 的请求在另一个仍在加载时得到答复。但是他们都在等待,当第一个请求完成时,他们都完成了。
我的代码和输出:
期望控制台输出:
First request: 2017-11-22 22:23:22.093497
Second request: 2017-11-22 22:23:24.580052
Second answer: 2017-11-22 22:23:25.580509
First answer: 2017-11-22 22:23:37.579263
控制台输出
First request: 2017-11-22 22:23:22.093497
First answer: 2017-11-22 22:23:37.579263
Second request: 2017-11-22 22:23:37.580052
Second answer: 2017-11-22 22:23:37.580509
test_first.py:
import tornado.web
import datetime
class First(tornado.web.RequestHandler):
@tornado.web.asynchronous
async def get(self):
print("First request: " + str(datetime.datetime.now()))
for _ in range(1000000000):
pass
self.set_status(200)
self.write("OK")
self.finish()
print("First answer: " + str(datetime.datetime.now()))
test_second.py:
import tornado.web
import datetime
class Second(tornado.web.RequestHandler):
@tornado.web.asynchronous
async def get(self):
print("Second request: " + str(datetime.datetime.now()))
self.set_status(200)
self.write("OK")
self.finish()
print("Second answer: " + str(datetime.datetime.now()))
app.py:
import tornado
from test_first import First
from test_second import Second
class Application(tornado.web.Application):
def __init__(self):
ENDPOINTS = [
# USERS #
(r"/test-first", First),
(r"/test-second", Second)
]
SETTINGS = {
"debug": True,
"autoreload": True,
"serve_traceback": True,
"compress_response": True
}
tornado.web.Application.__init__(self, ENDPOINTS, SETTINGS)
if __name__ == "__main__":
print("dinliyor...")
Application().listen(8888)
tornado.ioloop.IOLoop.instance().start()
for _ in range(1000000000):
pass
这是一项 CPU 密集型任务。因此,它会阻止整个服务器。 Tornado 和几乎所有其他异步库都用于执行异步网络 I/O,这意味着,数据进来,数据出去——没有繁重的 CPU 任务。
要执行 CPU 绑定阻塞任务,您必须 运行 在单独的进程或线程中执行它,这样它就不会阻塞服务器。
但无论如何,要获得预期的输出,您可以使用 tornado.gen.sleep
.
First
处理程序
class First(tornado.web.RequestHandler):
@tornado.web.asynchronous
async def get(self):
print("First request: " + str(datetime.datetime.now()))
await tornado.gen.sleep(5) # sleep for 5 seconds
self.set_status(200)
...