我是龙卷风和蟒蛇的新手。几天前我开始写一个非阻塞的休息api,但我还没能完成任务。当我同时向此端点“localhost:8080 / async”发送两个请求时,第二个请求在20秒后响应!这说明我做错了什么。
MAX_WORKERS = 4
class ASYNCHandler(tornado.web.RequestHandler):
executor = ThreadPoolExecutor(max_workers=MAX_WORKERS)
counter = 0
def pow_task(self, x, y):
time.sleep(10)
return pow(x,y)
async def background_task(self):
future = ASYNCHandler.executor.submit(self.pow_task, 2, 3)
return future
@gen.coroutine
def get(self, *args, **kwargs):
future = yield from self.background_task()
response= dumps({"result":future.result()}, default=json_util.default)
print(response)
application = tornado.web.Application([
('/async', ASYNCHandler),
('/sync', SYNCHandler),
], db=db, debug=True)
application.listen(8888)
tornado.ioloop.IOLoop.current().start()
答案 0 :(得分:0)
永远不要在Tornado代码中使用time.sleep
!使用IOLoop.add_timeout稍后或在协程yield gen.sleep(n)
中安排回调。
答案 1 :(得分:0)
奇怪的是,返回ThreadPoolExecutor
未来,基本上阻止了龙卷风的事件循环。如果来自龙卷风团队的任何人都读到这个并知道原因,那么他们能解释一下吗?我曾计划在龙卷风中做一些线程,但在处理完这个问题后,我发现它不会像我原先预料的那样简单。在任何情况下,这里的代码都符合您的预期(我已经将您的原始示例缩小了一点,以便任何人都可以快速运行它):
from concurrent.futures import ThreadPoolExecutor
from json import dumps
import time
from tornado.platform.asyncio import to_tornado_future
from tornado.ioloop import IOLoop
from tornado import gen, web
MAX_WORKERS = 4
class ASYNCHandler(web.RequestHandler):
executor = ThreadPoolExecutor(max_workers=MAX_WORKERS)
counter = 0
def pow_task(self, x, y):
time.sleep(5)
return pow(x,y)
async def background_task(self):
future = self.executor.submit(self.pow_task, 2, 3)
result = await to_tornado_future(future) # convert to tornado future
return result
@gen.coroutine
def get(self, *args, **kwargs):
result = yield from self.background_task()
response = dumps({"result": result})
self.write(response)
application = web.Application([
('/async', ASYNCHandler),
], debug=True)
application.listen(8888)
IOLoop.current().start()
主要区别在于background_tasks()
方法。我将asyncio
future转换为tornado
future,等待结果,然后返回结果。您在问题中提供的代码,由于某种原因在background_task()
屈服时被阻止,而您无法await
结果,因为未来不是龙卷风的未来。
稍微不同的是,这个简单的示例可以使用单线程/异步设计轻松实现,并且您的代码也可以在没有线程的情况下完成。线程易于实现,但同样容易出错,并且可能导致非常棘手的情况。在尝试编写线程代码时,请记住this photo:)