You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Tornado无法处理并发请求?如何实现多请求同时处理?

Tornado异步框架无法并发处理请求的原因及解决方法

嘿,这个问题我太熟了!你遇到的其实是Tornado里同步阻塞操作抢占IO循环的典型坑,咱们一步步拆解清楚:

为什么会出现请求排队?

先看你的代码:MainHandler里的do_something()用了input()——这是个同步阻塞调用,会直接把Tornado唯一的IO循环线程给卡死。

Tornado的异步是单线程模型,所有请求、事件监听全靠这一个IO循环线程驱动。如果某个操作阻塞了这个线程(比如等用户输入、time.sleep()、同步数据库查询),那后面的请求只能乖乖排队,直到阻塞操作结束。

你加的@tornado.web.asynchronous装饰器其实只是告诉Tornado:“别自动帮我调用finish(),我自己来”,它并没有把你的方法变成异步的——你的do_something()还是实打实的同步阻塞代码,所以整个IO循环被锁死,/hello请求自然得等它做完才能处理。

怎么实现并发处理?

核心思路就是绝对不能让IO循环线程被阻塞,把同步阻塞操作改成异步方式。针对你的场景,给你两种可行的修改方案:

方案1:用协程+异步任务包装阻塞操作

把阻塞的input()放到单独的回调里,让IO循环在等待的时候能处理其他请求:

import tornado.ioloop
import tornado.web
from tornado.gen import coroutine, Task

class MainHandler(tornado.web.RequestHandler):
    @coroutine
    def get(self):
        yield self.do_something()
        self.write("FINISHED")
        self.finish()

    @coroutine
    def do_something(self):
        # 用Task把阻塞操作包装成异步任务,让出IO循环
        yield Task(tornado.ioloop.IOLoop.current().add_callback, self._handle_input)

    def _handle_input(self):
        inp = input("enter to continue")
        print(inp)

class HelloHandler(tornado.web.RequestHandler):
    def get(self):
        print("say hello")
        self.write("Hello bro")
        self.finish()  # 你原代码这里少了个括号,先补上!

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
        (r"/hello", HelloHandler)
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()

方案2:用线程池处理阻塞操作

如果是实际业务里的重型阻塞操作(比如同步调用第三方API),可以用Tornado的ThreadPoolExecutor把操作放到线程池里,不占用IO循环线程:

import tornado.ioloop
import tornado.web
from tornado.gen import coroutine
from concurrent.futures import ThreadPoolExecutor

executor = ThreadPoolExecutor(2)

class MainHandler(tornado.web.RequestHandler):
    @coroutine
    def get(self):
        yield self.do_something()
        self.write("FINISHED")
        self.finish()

    @coroutine
    def do_something(self):
        # 把阻塞操作提交到线程池
        inp = yield executor.submit(input, "enter to continue")
        print(inp)

# HelloHandler和make_app部分和上面一致

关键知识点再强调

  • Tornado是单线程异步框架,IO循环是核心,绝对不能让它被同步操作阻塞。
  • 所有耗时IO操作(数据库、HTTP请求、文件读写)都要用Tornado提供的异步客户端,或者用线程/进程池包装。
  • @tornado.web.asynchronous不是“魔法异步开关”,它只是控制finish()的调用时机,真正的异步要靠协程、回调或者线程池实现。

另外提一句:你原代码里HelloHandler的finish()少了个右括号,记得补上哦!

内容的提问来源于stack exchange,提问作者vinaykp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:10:08