我刚接触龙卷风,有一个API可以进行阻塞数据库调用。由于这个阻塞调用,如果多个请求同时到来,龙卷风就无法服务所有请求。
我仔细研究了一下,发现可以使用两种方法来解决这个问题:使代码异步和/或使用进程池执行器。我在这里的假设是,拥有多个进程池执行器就像龙卷风上有多个进程来服务多个请求一样。我看到的关于实现进程池执行器的每一个例子都使代码异步。
我暂时不能使代码异步,因为这需要更多的代码更改,所以我正在考虑使用进程池执行器进行简单的修复。
我目前拥有的
import tornado.ioloop
import tornado.web
def blocking_call():
import time
time.sleep(60)
return "Done"
class MainHandler(tornado.web.RequestHandler):
def get(self):
val = blocking_call()
self.write(val)
if __name__ == "__main__":
app = tornado.web.Application([(r"/", MainHandler)])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
我尝试了
import tornado.ioloop
import tornado.web
from concurrent.futures import ProcessPoolExecutor
def blocking_call():
import time
time.sleep(60)
return "Done"
class MainHandler(tornado.web.RequestHandler):
def initialize(self, executor):
self.executor = executor
def get(self):
val = self.executor.submit(blocking_call)
self.write(val)
if __name__ == "__main__":
executor = ProcessPoolExecutor(5)
app = tornado.web.Application(
[(r"/", MainHandler, dict(executor=executor))])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
我对这种方法的问题是,现在我得到的是future object
,而不是实际的响应。如何让Get
请求等待self.executor
完成后再发送回响应?
executor.submit()
返回一个不可用的concurrent.futures.Future
。
我建议您使用Tornado的run_in_executor
方法来执行阻塞任务。
async def get(self):
loop = tornado.ioloop.IOLoop.current()
val = await loop.run_in_executor(self.executor, blocking_call)
self.write(val)